Reload data when using FutureBuilder
what i did an it worked for me, is to call the future function again in setState(). in your example it will looks like this.
first you assign your _getData() future function to a variable (_myData) with the same return type, after that, you can override it's value in setState() that will rebuild the UI and therefor run the future again.
in code it will looks like this.(from you example):
class _MyHomePageState extends State<MyHomePage> {
Future<List<String>> _myData = _getData(); //<== (1) here is your Future
@override
Widget build(BuildContext context) {
var futureBuilder = new FutureBuilder(
future: _myData; //<== (2) here you provide the variable (as a future)
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return new Text('loading...');
default:
if (snapshot.hasError)
return Column(
children: [
Icon(Icons.error),
Text('Failed to fetch data.'),
RaisedButton(
child: Text('RETRY'),
onPressed: (){
setState(){
_myData = _getData(); //<== (3) that will trigger the UI to rebuild an run the Future again
}
},
),
],
);
else
return createListView(context, snapshot);
}
},
);
return new Scaffold(
appBar: new AppBar(
title: new Text("Home Page"),
),
body: futureBuilder,
);
}
I did a deep dive into this and it's not that difficult. The builder is properly rebuilt on changing the future (if you trigger the change with setState
). Problem is, the hasData
and hasError
aren't reset until the response is back. But we can use connectionState
instead.
final builder = FutureBuilder(
future: _future,
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return _buildLoader();
}
if (snapshot.hasError) {
return _buildError();
}
if (snapshot.hasData) {
return _buildDataView();
}
return _buildNoData();
});
Here's a post on the issue and a linked repo showing the issue and solution: https://www.greycastle.se/reloading-future-with-flutter-futurebuilder/
Widget createListView(BuildContext context, AsyncSnapshot snapshot) {
RaisedButton button = RaisedButton(
onPressed: () {
setState(() {});
},
child: Text('Refresh'),
);
//.. here create widget with snapshot data and with necessary button
}