Reputation: 1792
I'm a little confused about how to implement Flutter's FutureBuilder according to the docs. I have a Future Builder here which work, with the only problem being that it every time the build method is run so to is the future being used:
FutureBuilder(
future: DBProvider.db.getUser(),
builder: (_, userData) {
switch (userData.connectionState) {
case ConnectionState.none:
return Container();
case ConnectionState.waiting:
return Container();
case ConnectionState.active:
case ConnectionState.done:
newUser = userData.data;
return ListView(
shrinkWrap: true,
children: <Widget>[
... // Lot's of things
],
);
}
return null;
},
),
I then realize the importance of this part of the docs where it says the future must be "obtained earlier" so this problem doesn't happen:
The future must have been obtained earlier, e.g. during State.initState, State.didUpdateConfig, or State.didChangeDependencies. It must not be created during the State.build or StatelessWidget.build method call when constructing the FutureBuilder. If the future is created at the same time as the FutureBuilder, then every time the FutureBuilder's parent is rebuilt, the asynchronous task will be restarted.
Here's where my question comes from, I understand what those words are saying, but in terms of writing the code according to that what exactly does mean / look like?
Do I simply make a function and call it in initState like this:
@override
void initState() {
super.initState();
_getUser();
}
_getUser() async {
newUser = await DBProvider.db.getUser();
}
In this case what goes in the future argument of the FutureBuilder? Or this completely not right?
Upvotes: 1
Views: 1177
Reputation: 5818
Yes, you are on the right track. The easiest way to deal with this is to store a Future variable in your state. In initState
make the API call and store the Future. You can then pass this Future to FutureBuilder.
Something like this:
class MyWidget extends StatefulWidget {
State createState() {
return MyState();
}
}
class MyState extends State<MyWidget> {
Future userFuture;
void initState() {
super.initState();
// Note here we are not awaiting the user, but rather storing
// the future in the variable
userFuture = DBProvider.db.getUser();
}
Widget build(BuildContext context) {
return FutureBuilder(
future: userFuture,
builder: (BuildContext, snapshot) {
...
}
);
}
}
Upvotes: 2