我在加载小部件时正在加载数据,如下面的代码。 UI完全加载后,我想添加一个刷新按钮以再次重新加载数据。
如何刷新视图?
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
var futureBuilder = new FutureBuilder(
future: _getData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return new Text('loading...');
default:
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
else
return createListView(context, snapshot);
}
},
);
return new Scaffold(
appBar: new AppBar(
title: new Text("Home Page"),
),
body: futureBuilder,
);
}
Future<List<String>> _getData() async {
var values = new List<String>();
await new Future.delayed(new Duration(seconds: 5));
return values;
}
Widget createListView(BuildContext context, AsyncSnapshot snapshot) {
}
}
答案 0 :(得分:11)
我对此进行了深入研究,这并不困难。在更改未来时会正确重建构建器(如果您通过setState
触发更改)。问题是,hasData
和hasError
直到返回响应后才重置。但是我们可以改用connectionState
。
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();
});
有关此问题的帖子和显示该问题及解决方案的链接回购: https://www.greycastle.se/reloading-future-with-flutter-futurebuilder/
答案 1 :(得分:4)
Widget createListView(BuildContext context, AsyncSnapshot snapshot) {
RaisedButton button = RaisedButton(onPressed: () {
setState(() {});
}, child: Text('Refresh'),);
//.. here create widget with snapshot data and with necessary button
}
答案 2 :(得分:0)
您可以通过单击FlatButton刷新小部件。代码如下。
class _MyHomePageState extends State<MyHomePage> {
String display;
Widget futureBuilder() {
return new FutureBuilder<String>(builder: (context, snapshot) {
// if(snapshot.hasData){return new Text(display);} //does not display updated text
if (display != null) {
return new Text(display);
// return your createListView(context, snapshot);
}
return new Text("no data yet");
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Home Page"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlatButton(onPressed: () async{
result = await _getData();
print(result);
// Result will be your json response
setState(() {
display = result; //assign any string value from result to display variable.
});
},
child: new Text("Get Data")
),
futureBuilder()
],
),
),
);
}
Future<List<String>> _getData() async {
var values = new List<String>();
await new Future.delayed(new Duration(seconds: 5));
return values;
}
Widget createListView(BuildContext context, AsyncSnapshot snapshot) {
}
}
答案 3 :(得分:0)
我为我所做的工作是在setState()中再次调用future函数。 在您的示例中,它看起来像这样。
首先,将_getData()未来函数分配给具有相同返回类型的变量(_myData),之后,可以在setState()中覆盖其值,该值将重建UI并因此再次运行Future。
在代码中看起来像这样。(从您的示例中):
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,
);
}