Reload data when using FutureBuilder

fif*_*man 5 flutter flutter-layout

我在加载小部件时加载数据,如下面的代码。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) {

      }
    }
Run Code Online (Sandbox Code Playgroud)

Alm*_*und 20

我对此进行了深入研究,这并不困难。构建器会在更改未来时正确重建(如果您使用 触发更改setState)。问题是,在响应返回之前hasDatahasError不会重置。但我们可以用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();
});
Run Code Online (Sandbox Code Playgroud)

这是关于该问题的帖子以及显示问题和解决方案的链接存储库: https://www.greycastle.se/reloading-future-with-flutter-futurebuilder/

  • 我不敢相信这是正确的答案(但确实如此)。我每天对颤振越来越没有信心。为什么不使用 widget.reload() 呢?为什么快照没有重置。看起来 flutter 需要很多 hacky 解决方案。 (4认同)

kor*_*hix 11

我所做的对我有用的是在 setState() 中再次调用 future 函数。在您的示例中,它看起来像这样。

首先,您将 _getData() 未来函数分配给具有相同返回类型的变量 (_myData),之后,您可以在 setState() 中覆盖它的值,该值将重建 UI 并因此再次运行未来。

在代码中它看起来像这样。(来自你的例子):

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,
        );
      }
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是最合适的方法(并且根据文档)。https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html (2认同)

And*_*sky 10

Widget createListView(BuildContext context, AsyncSnapshot snapshot) {
  RaisedButton button = RaisedButton(onPressed: () {
    setState(() {});
  }, child: Text('Refresh'),);
  //.. here create widget with snapshot data and with necessary button
}
Run Code Online (Sandbox Code Playgroud)

  • 它将再次调用`build` 方法。并且 `FutureBuilder` 从 `_getData()` 方法中获取数据 (5认同)
  • 设置状态((){});会重新加载数据吗? (2认同)