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
builder
function: This function returns a widget based on the latestAsyncSnapshot
from 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.waiting
orConnectionState.done
.snapshot.hasData
: A boolean that istrue
if theFuture
completed successfully with a non-null value.snapshot.hasError
: A boolean that istrue
if theFuture
failed.snapshot.data
: The data returned by theFuture
upon successful completion.snapshot.error
: The error object if theFuture
failed.
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 theFuture
is only created once. FutureBuilder
listens to_dataFuture
.- The
builder
function shows aCircularProgressIndicator
while 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! 🚀