1

我需要在页面渲染之前从三个不同的 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

就这样继续下去……

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

4

2 回答 2

3

不要在FutureBuilder

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

未来必须更早获得,例如在 State.initState、State.didUpdateConfig 或 State.didChangeDependencies 期间。在构造 FutureBuilder 时,不能在 State.build 或 StatelessWidget.build 方法调用期间创建它。如果future与FutureBuilder同时创建,那么每次FutureBuilder的parent重建时,异步任务都会重新启动。

于 2019-02-11T16:07:35.767 回答
1

Here is a possible right solution. This makes your data load just one time inside scaffold. First make sure you are using stateful widget.

Define your data:

Future<List<Data>> futureList;

Make a function to fetch your data from backend:

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

Load your function in init state:

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

Call your fetched data in future builder:

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());
        }
      },
    );
于 2020-09-06T21:30:40.993 回答