【问题标题】:Future builder(future:) is recursing my http requests,Future builder(future:) 正在递归我的 http 请求,
【发布时间】:2019-07-05 02:58:58
【问题描述】:

我需要在页面渲染之前从三个不同的 url 获取数据。所以, 这是我的 ScopedModel 中的方法,包括多个 http.post 方法:

Future fetchData() async {
  _isLoading = true;
  notifyListeners();
  await fetchAvailable();
  await fetchOnProgress();
  await fetchCompleted();
  _isLoading = false;
  notifyListeners();

}

fetchData 区域内的方法只是带有原始 Future 类型的经典 http.post 请求。

这是我的 FutureBuilder:

FutureBuilder(
        future: model.fetchData(),
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          return snapshot.connectionState != ConnectionState.done
              ? Center(
                  child: CircularProgressIndicator(),
                )
              : Column.......

问题是,“未来”功能,它不断执行,永无止境。我关于从服务器获取 json 的算法将正文中的变量膨胀到 ListView.builder 后代中。

输出如我所说的递归发布请求。此外,我正在获取此日志,行数增量如 1 - 2 - 3 或 2 - 4 - 6 -8 等。

uid=10085(my.package.directory) 1.ui identical 1 lines
.......Other logs here
uid=10085(my.package.directory) 1.ui identical 3 lines

就这样继续下去……

另外,还有什么其他有用的方法可以在页面渲染之前处理这么少量的数据?

【问题讨论】:

  • 有什么问题?
  • @Edman 好的,我让问题更清楚了。

标签: dart flutter


【解决方案1】:

不要在FutureBuilder中发出HTTP请求

https://docs.flutter.io/flutter/widgets/FutureBuilder-class.html

未来一定是更早获得的,例如期间 State.initState、State.didUpdateConfig 或 State.didChangeDependencies。期间不得创建 构造时调用 State.build 或 StatelessWidget.build 方法 未来建造者。如果未来与 FutureBuilder,那么每次 FutureBuilder 的父级重建时, 异步任务将重新启动。

【讨论】:

  • 在这里我创建了这样的 initState:@override void initState() { MainModel model = ScopedModel.of(context);模型.fetchData(); super.initState();但它不起作用,同样的递归作用......
  • 确保fetchData()在之前已经获取过数据的情况下不会再次获取,例如通过缓存数据。
  • 感谢您的努力!我将请求转移到单个请求,model.fetchData() 的用法只是 initState 和 FutureBuilder,仅此而已,但仍在递归...
  • 谢谢您,我明天会尝试您的建议并报告结果。我认为建设者是问题所在。
  • 再次感谢甘特!我已经处理了它,将所有数据处理移到了 ScopedModel 中。此外,还有一些小的嵌套数据类型错误,小部件类型现在是 StatelessWidget。对于 FutureBuilder 用户,我建议他们最好使用快照来使用获取的数据而不是字段。
【解决方案2】:

这是一个可能的正确解决方案。这使您的数据在脚手架内只加载一次。首先确保您使用的是有状态小部件。

定义您的数据:

Future<List<Data>> futureList;

创建一个从后端获取数据的函数:

Future<void> getList() async {
    final provider = Provider.of<DataProvider>(context, listen: false);
    final list = provider.getData();
    setState((){
      futureList = list;
    });
  }

在初始化状态下加载你的函数:

@override
  void initState() {
    super.initState();
    Future.delayed(Duration.zero, () {
      getList();
    });
  }

在未来的构建器中调用您获取的数据:

Widget _body(BuildContext context) {
    return FutureBuilder(
      future: futureList,
      builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
        if (snapshot.hasData) {
          if(snapshot.data.length == 0){
            return Center(child: Text('List is empty'));
          }else {
            return ListView.builder(
                padding: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
                itemBuilder: (BuildContext context, int index) {
                  return GestureDetector(
                      child: DataItem(
                        index: index,
                        dataClass: snapshot.data[index],
                      ),
                      onTap: () {});
                },
                itemCount: snapshot.data.length);
          }
        } else {
          return Center(child: CircularProgressIndicator());
        }
      },
    );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-04
    • 2023-02-08
    • 1970-01-01
    • 2021-03-02
    • 2022-06-21
    • 2021-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多