A Guide to FutureBuilder in Flutter
A Guide to FutureBuilder in Flutter
When building Flutter applications, you’ll often need to perform asynchronous operations, like fetching data from a network or reading from a database. A Future is Dart’s way of handling these one-time asynchronous events. But how do you update your UI when the Future completes?
This is where FutureBuilder comes in. It’s a powerful widget that listens to a Future and rebuilds its UI based on the Future’s current state, making it incredibly easy to create reactive and responsive user interfaces.
🤔 What is FutureBuilder?
The FutureBuilder widget is designed to work with a Future. It takes a Future and a builder function as arguments. The builder function is responsible for deciding what to show on the screen based on the Future’s state: whether it’s still waiting, has completed with data, or has failed with an error.
This saves you from manually managing State and calling setState() to update your UI when the Future completes.
🛠️ How to Use FutureBuilder
Using FutureBuilder involves two main parts:
- Providing the
Future: This is the asynchronous operation you want to listen to. - Implementing the
builderfunction: This function returns a widget based on the latestAsyncSnapshotfrom theFuture.
The builder Function and AsyncSnapshot
The builder function gives you an AsyncSnapshot, which contains information about the Future’s state. Here are the most important properties:
snapshot.connectionState: An enum that tells you the current state of the connection. You’ll most often check if it’sConnectionState.waitingorConnectionState.done.snapshot.hasData: A boolean that istrueif theFuturecompleted successfully with a non-null value.snapshot.hasError: A boolean that istrueif theFuturefailed.snapshot.data: The data returned by theFutureupon successful completion.snapshot.error: The error object if theFuturefailed.
Example: Fetching Data from a Simulated API
Let’s build a simple app that fetches a piece of data and displays it. We’ll simulate a network call with a Future.delayed.
a. Create a Function that Returns a Future
First, let’s define a function that simulates fetching data. This function will return a Future<String> after a 2-second delay.
Future<String> fetchData() async {
// Simulate a network request
await Future.delayed(Duration(seconds: 2));
// Return a piece of data
return "Data fetched successfully!";
// To test the error state, you can throw an exception:
// throw Exception('Failed to fetch data');
}
b. Use FutureBuilder in the UI
Now, we’ll use FutureBuilder to listen to fetchData() and update the UI accordingly.
import 'package:flutter/material.dart';
class MyDataScreen extends StatefulWidget {
@override
_MyDataScreenState createState() => _MyDataScreenState();
}
class _MyDataScreenState extends State<MyDataScreen> {
late Future<String> _dataFuture;
@override
void initState() {
super.initState();
_dataFuture = fetchData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('FutureBuilder Example'),
),
body: Center(
child: FutureBuilder<String>(
future: _dataFuture, // The Future to listen to
builder: (context, snapshot) {
// 1. Check the connection state
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
}
// 2. Check for errors
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
}
// 3. Check for data
if (snapshot.hasData) {
return Text(
snapshot.data!,
style: TextStyle(fontSize: 24),
);
}
// 4. Default case (should not be reached in this example)
return Text('No data yet.');
},
),
),
);
}
}
In this example:
- We call
fetchData()ininitState()to ensure theFutureis only created once. FutureBuilderlistens to_dataFuture.- The
builderfunction shows aCircularProgressIndicatorwhile waiting, an error message on failure, and the fetched data on success.
✅ When to Use FutureBuilder
FutureBuilder is ideal for:
- Fetching data from an API when a screen loads.
- Reading data from a local database or file.
- Any one-time asynchronous operation where the result is needed to build a part of your UI.
📚 Resources
Happy coding! 🚀