Async Await and Future: If You Do, Then You’ve Cracked Flutter

Home » Flutter » Async Await and Future: If You Do, Then You’ve Cracked Flutter

You might wonder why await, async, and Future are essential for mastering Flutter app development. Yes, it’s true. You can’t skip these asynchronous programming concepts in Flutter because they play a major role in developing complex applications with Dart.

Async Await and Future: If You Do, Then You've Cracked Flutter

Async Await and Future in Flutter

In Flutter, managing asynchronous operations is crucial for building responsive apps. Understanding Async Await and Future in Flutter can enhance your coding skills and app performance. This tutorial will guide you through these concepts with simple examples.

Understanding Future

A Future represents a potential value or error that will be available at some point. It is an essential part of handling asynchronous operations in Flutter. For instance, fetching data from a server or reading a file from the device storage returns a Future.

Creating a Future (Dart)

You can create a Future in several ways. Let’s use the Future constructor.

Here’s a basic example:

Future<String> getData() 
{
  return Future.delayed(Duration(seconds: 3),() => 'I got data.');
}

In this example, getData simulates a network request. It returns a Future that completes after 3 seconds with the string ‘I got data.’.

Dart Program (main.dart)

To call the getData function in the main function and properly handle the asynchronous operation, you need to use the async and await keywords.

void main() async
{
  String data = await getData();
  print(data);
}

Future<String> getData() 
{
  return Future.delayed(Duration(seconds: 3),() => 'I got data.');
}
I got data. // after 3 seconds

Here’s a step-by-step explanation:

Mark the main Function as async

Add the async keyword to the main function. This allows you to use the await keyword inside it.

Use await to Call getData

The await keyword pauses the execution of the main function until getData completes. The result is then stored in the data variable.

Print the Result

Finally, print the data to see the result of the getData function.

Async and Await Keywords

The async and await keywords simplify working with futures. They make your asynchronous code look synchronous, improving readability.

Using Async

To define an asynchronous function, add the async keyword to the function.

Future<String> fetchData() async {
  await Future.delayed(Duration(seconds: 3));
  return 'Data fetched!!';
}

Using Await

The await keyword pauses the execution until the Future completes. You can only use await inside an async function.

void main() async
{
  String data = await getData();
  print(data);
}

How to handle errors?

When working with futures, handling errors is crucial. Use the try-catch block to catch exceptions.

Future<String> fetchData() async {
  try {
    await Future.delayed(Duration(seconds: 2));
    return 'Data fetched!!';
  } catch (e) {
    return 'Error occurred!';
  }
}

Now, if an error occurs, the function returns ‘Error occurred!’ instead of crashing.

Chaining Futures

You can chain multiple futures using the then method. This method allows you to perform actions when a future completes.

Future<String> fetchData() {
  return Future.delayed(Duration(seconds: 2), () => 'Data fetched!')
    .then((value) => 'Processed $value');
}

Flutter async await example

Let’s see a real-world example. We will fetch data from a public API using Async Await and Future in Flutter.

Step 1: Add the HTTP Package

First, add the http package to your pubspec.yaml file.

dependencies:
  http: ^0.13.3

Then, import it in your Dart file.

import 'package:http/http.dart' as http;

Step 2: Create the Fetch Function

Create an asynchronous function to fetch data from the API.

Write the following code on DartPad:

import 'package:http/http.dart' as http;

void main() async {
  
  String response = await fetchApiData();
  print(response);
  
}

Future<String> fetchApiData() async {
  final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));

  if (response.statusCode == 200) {
    return response.body;
  } else {
    throw Exception('Failed to load data');
  }
}

Output

{
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}

Let’s use with Flutter widgets

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';  // Import the Dart convert library for JSON decoding

Future<Map<String, dynamic>> fetchApiData() async {
  final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));

  if (response.statusCode == 200) {
    return json.decode(response.body);  // Parse the JSON response
  } else {
    throw Exception('Failed to load data');
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Async Await and Future in Flutter'),
        ),
        body: Center(
          child: FutureBuilder<Map<String, dynamic>>(
            future: fetchApiData(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return CircularProgressIndicator();
              } else if (snapshot.hasError) {
                return Text('Error: ${snapshot.error}');
              } else if (snapshot.hasData) {
                return Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text('Title: ${snapshot.data!['title']}'),
                    SizedBox(height: 10),  
                    Text('Body: ${snapshot.data!['body']}'),
                  ],
                );
              } else {
                return Text('No data');
              }
            },
          ),
        ),
      ),
    );
  }
}

You can handle asynchronous operations efficiently, making your apps more responsive. Start using these concepts today to improve your Flutter projects.

Happy Fluttering!

You may also like...