How to get data from async function to show on a widget


This article is about a very useful widget of Flutter, the Future builder widget.

When you want to show some async function result on a widget you will face some troubles because a widget’s build sync method will not wait while fetching data. Flutter provides a better answer to this question. It is the Future Builder widget.

This is the asynchronous function I used to explain how the Future Builder widget works. This function simply returns a String object.

1
2
3
4
Future<String> getUserName(int userID) async {
String userName = await DatabaseService().getUserName(userID);
return userName;
}

The below codes show a builder function and how we can use the FutureBuilder widget to show the data returns by the above code.


Method 1 (using connection states)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Widget build(BuildContext context) {
return FutureBuilder(
future: getUserName(1),
builder: (BuildContext context, AsyncSnapshot<String> userNameSnapshot) {
Widget widget;
if (userNameSnapshot.connectionState == ConnectionState.done) {
widget = Text(userNameSnapshot.data)
} else {
widget = Container(
color: Colors.white,
child: Center(
child: CircularProgressIndicator(),
),
);
}
return widget;
},
);
}

In this example, the future function getUserName() is called in the future. When this method returns data, the userNameSnapshot object’s connection state will be equal to ConnectionState.done and the builder will return the text widget.

There are three connection states of AsyncSnapshot.

  • ConnectionState.none — Not currently connected to any asynchronous computation. For example, a FutureBuilder whose FutureBuilder.future is null.
  • ConnectionState.waiting — Connected to an asynchronous computation and awaiting interaction.
  • ConnectionState.done — Connected to a terminated asynchronous computation.

Here I showed one way of handling async function results using the Future Builder widget. There is another method to handle this using the states(hasData and hasError) of AsyncSnapshot.


Method 2 (using hasData and hasError states)

We can use hasData and hasError states of AsyncSnapshot to handle the Future Builder widget.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Widget build(BuildContext context) {
return FutureBuilder(
future: getUserName(1),
builder: (BuildContext context, AsyncSnapshot<String> userNameSnapshot) {
Widget widget;
if (userNameSnapshot.hasData) {
widget = Text(userNameSnapshot.data)
} else if(userNameSnapshot.hasError){
widget = Text('Error: ${userNameSnapshot.error}')
} else {
widget = Container(
color: Colors.white,
child: Center(
child: CircularProgressIndicator(),
),
);
}
return widget;
},
);
}

Basically userNameSnapshot.hasData returns true when AsyncSnapshot is with data and otherwise, it returns false, userNameSnapshot.hasErrorreturns true when AsyncSnapshot is with error(s) or else it returns false.

Likewise, we can use these two methods to show async function results on widgets.