I have problems with FutureBuilder starting twice. First it fetch the data correctly, returning my StartScreen, then after few seconds, the StartScreen rebuilds and I noticed that the FutureBuilder fires again.
Here is my code and it's pretty simple, so I wonder what may the problem be?!?
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
FirebaseUser user;
@override
void initState() {
// TODO: implement initState
super.initState();
getNewestlocation();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'APP',
theme: buildTheme(),
home: FutureBuilder<FirebaseUser>(
future: Provider.of<AuthService>(context).getUser(),
builder: (context, AsyncSnapshot<FirebaseUser> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.error != null) {
print('error');
return Text(snapshot.error.toString());
}
user = snapshot.data;
print('user here $user');
return snapshot.hasData ? StartScreen(user) : LoginScreen();
} else {
return LoadingCircle();
}
},
),
);
}
}
Can anyone help me with this, please?
It's meant to represent any widget that triggers rebuilds like, for example, a user scrolling a ListView . The screen is split in two: Top: a StatelessWidget containing a FutureBuilder . It's fed a new Future that resolves to the current date in seconds.
Show a constructor and parameters of Streambuilder. That is the way to utilize FutureBuilder in Flutter. You need to make a Future and pass it as the future argument. The snapshots of the Future will be passed to the builder function, in which you can decide the format to be shown depending on the current snapshot.
The future is firing again because you're creating it in the build method at the same time as the FutureBuilder.
From the FutureBuilder docs:
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.
So to prevent it from firing you'd have to do something like this:
class _MyAppState extends State<MyApp> {
Future<String> _myString;
@override
void initState() {
super.initState();
_myString = _fetchString();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _myString,
builder: (context, snapshot) {
// build page stuff...
},
),
);
}
}
Future<String> _fetchString() async {
print('running future function');
await Future.delayed(Duration(seconds: 3));
return 'potatoes';
}
Note, to access a provider in initState() you have to set listen to false, as detailed in this answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With