【问题标题】:How to load list only after FutureBuilder gets snapshot.data?如何仅在 FutureBuilder 获取 snapshot.data 后加载列表?
【发布时间】:2020-11-30 19:51:21
【问题描述】:

我有一个 JSON 方法,它在完成后返回 List

Future<List<Feed>> getData() async {
  List<Feed> list;
  String link =
      "https://example.com/json";
  var res = await http.get(link);
  if (res.statusCode == 200) {
    var data = json.decode(res.body);
    var rest = data["feed"] as List;
    list = rest.map<Feed>((json) => Feed.fromJson(json)).toList();
  }
  return list;
}

然后我在我的 initState() 中调用它,其中包含一个列表 hello,它将过滤掉 JSON 列表,但它首先在屏幕上显示一个 null 列表,几秒钟后它加载列表。

    getData().then((usersFromServer) { 
          setState(() {.   //Rebuild once it fetches the data
hello = usersFromServer
          .where((u) => (u.category.userJSON
              .toLowerCase()
              .contains('hello'.toLowerCase())))
          .toList();
            users = usersFromServer;
            filteredUsers = users;
          });
        });

这是我在 build() 方法中调用的 FutureBuilder,但是如果我在 return 语句之前提供 hello 列表,它表明方法 where() 是在 null 上调用的(我是用于过滤掉hello())

FutureBuilder(
            future: getData(),
            builder: (context, snapshot) {
              return snapshot.data != null ?
                Stack(
                  children: <Widget>[
                    CustomScrollView(slivers: <Widget>[
                      SliverGrid(
  gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
    maxCrossAxisExtent: 200.0,
    mainAxisSpacing: 10.0,
    crossAxisSpacing: 10.0,
    childAspectRatio: 4.0,
  ),
  delegate: SliverChildBuilderDelegate(
    (BuildContext context, int index) {
      return Container(
        child: puzzle[0],
      );
    },
    childCount: 1,
  ),
)
                    ]),
                  ],
                )
               :
               CircularProgressIndicator();
              
            });

【问题讨论】:

    标签: flutter dart future flutter-futurebuilder


    【解决方案1】:

    您多次调用 getData 方法。不要那样做。您的 UI 等待一个呼叫,而您的代码等待另一个呼叫。那是一团糟。调用它一次并等待那个调用。

    您需要定义在您的状态下等待的未来:

    Future<void> dataRetrievalAndFiltering;
    

    然后在您的initstate 中,将整个操作分配给这个未来:

    (请注意,我完全删除了 setState,这里不再需要它了)

    dataRetrievalAndFiltering = getData().then((usersFromServer) { 
          hello = usersFromServer.where((u) => (u.category.userJSON.toLowerCase().contains('hello'.toLowerCase()))).toList();
            users = usersFromServer;
            filteredUsers = users;
          
        });
    

    现在你的FurtureBuilder实际上可以等待那个特定的未来,而不是你通过再次调用你的方法生成的一个新的未来:

    FutureBuilder(
            future: dataRetrievalAndFiltering,
            builder: (context, snapshot) {
    

    现在你有了一个未来,你可以等待。

    【讨论】:

    • 嗨,所以我按照你的建议进行了更改,但是我的未来不会返回 snapshot.data 并且卡在 CircularProgressIndicator()
    • 是的,你是对的。您想在该列表中显示什么?用户?饲料?您需要在您的.then() 中返回它,并将Future&lt;void&gt; 变成Future&lt;List&lt;?&gt;&gt;,其中? 是您要在列表中显示的类型。
    • 或者,您可以查询snapshot.connectionState 以显示您的进度指示器,因为我们不会从未来返回任何内容,我们将其写入变量中。所以我们需要的只是等待部分。
    • 好吧,我所做的是,我从 Future 中删除了 .then 参数,并直接为你好、用户和过滤用户调用了 snapshot.data,它开始工作了!感谢您的帮助
    猜你喜欢
    • 1970-01-01
    • 2021-10-08
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 2020-05-02
    • 2021-08-29
    相关资源
    最近更新 更多