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 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!