【问题标题】:Reload data when using FutureBuilder使用 FutureBuilder 时重新加载数据
【发布时间】:2023-04-04 16:22:01
【问题描述】:

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

      }
    }

【问题讨论】:

  • 我不明白 - 你为什么不在createListView 方法中添加这个按钮?

标签: flutter flutter-layout


【解决方案1】:
Widget createListView(BuildContext context, AsyncSnapshot snapshot) {
  RaisedButton button = RaisedButton(
    onPressed: () {
      setState(() {});
    },
    child: Text('Refresh'),
  );
  //.. here create widget with snapshot data and with necessary button
}

【讨论】:

  • @Jake Calling _getData() from onPressed 返回 Future 并且不会改变 UI 中的任何内容
  • 如您所见,正在使用future: _getData() 加载数据... setState 将如何再次绑定数据?
  • setState(() {});会重新加载数据吗?
  • 它会再次调用build方法。而FutureBuilder_getData()方法中获取数据
  • @fifachapman 因为_getData()FutureBuilder 内,通过setState(() {}); 重新加载此段将依次重新加载数据
【解决方案2】:

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

首先,您将 _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,
        );
      }

【讨论】:

【解决方案3】:

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

【讨论】:

    【解决方案4】:

    您可以通过单击 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) {
    
      }
    }
    

    【讨论】:

    • 关于如何在无状态小部件中刷新的任何想法?
    猜你喜欢
    • 2023-01-19
    • 2022-01-02
    • 1970-01-01
    • 2020-06-18
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-04
    相关资源
    最近更新 更多