使用FutureBuilder时重新加载数据

时间:2018-11-06 10:46:50

标签: 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) {

      }
    }

4 个答案:

答案 0 :(得分:11)

我对此进行了深入研究,这并不困难。在更改未来时会正确重建构建器(如果您通过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();
});

有关此问题的帖子和显示该问题及解决方案的链接回购: 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,
        );
      }