FutureBuilder 与 Notifylistener 冲突

FutureBuilder conflict with Notifylistener

我的提供程序文件中有一个类似这样的方法来更新来自服务器的项目列表:

Future<void> getServerMeals(String userName, String date) async {
    final QueryBuilder<ParseObject> parseQuery =
        QueryBuilder<ParseObject>(ParseObject('UsersEaten'));

    parseQuery
      ..whereContains('eatenBy', userName)
      ..whereEqualTo('eatenDate', date);

    final ParseResponse apiResponse = await parseQuery.query();

    if (apiResponse.success && apiResponse.results != null) {
      List<dynamic>? apiRes = apiResponse.results;

      List<dynamic> newMeals = apiRes!
          .map((e) => EatenItem(
                id: e['objectId'],
                eatenCal: e['eatenCal'],
                eatenTitle: e['eatenTitle'],
                eatenImageUrl: e['eatenImg'],
                userId: e['objectId'],
              ))
          .toList();
      _eatenMeals = newMeals;
      print(apiResponse.results);
     
    }
  }

在我的主屏幕中,我将该列表包装到 FutureBuilder 中,它工作正常,return 一个列表:


 Container(
          height: MediaQuery.of(context).size.height * 0.6,
          margin: EdgeInsets.only(left: 30, right: 30),
          child: FutureBuilder(
            builder: (ctx, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return Center(
                  child: CircularProgressIndicator(),
                );
              }

              return ListView.builder(
                itemCount: mealsList.eatenMeals.length,
                itemBuilder: (ctx, index) =>
                    DailyEaten(mealsList.eatenMeals[index]),
              );
            },
            future: Provider.of<EatenMeals>(context)
                .getServerMeals(currentUser.username, now),
          ),
        ),

但是当我在我的方法中添加 notifylistener() 时,我未来的构建器列表停留在等待状态并且不会更新列表这里有什么问题

问题是你正在用你的构建方法创造你的未来。

这意味着在每次构建时,您都会再次创造这个未来。

这是你程序中的一个小麻烦和错误,直到你还添加了未来 本身 触发了 rebuild,它意味着它将 运行,触发重建,重建将等待 new 未来,这将 运行,触发重建,再次创建 new 未来……你懂的。这是一个无尽的循环,运行建立一个未来只是为了重建和 运行 它再次。

您必须创建您的 Future 在构建方法之外。构建方法可以被多次触发。仅在构建方法中引用 Future<> 类型变量并在另一个方法中分配该变量,可能是 init 或有人单击按钮时的某些 setState 调用。

这是因为调用notifyListeners会重建build方法(你调用Provider.of...的方法),这会产生一个循环。(build 方法调用 future 并且 notifyListener 将重建 build 方法,并且此过程将永远持续下去)。

为防止这种情况,请为 of 方法提供另一个参数:listen: false

Provider.of<EatenMeals>(context, listen: false).getServerMeals(currentUser.username, now);

这将阻止 build 方法重建。

@nvoigt

这是我的小部件,我已经从构建方法中删除了那些提供程序


class TimelineWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
  
    return Column(
      mainAxisAlignment: MainAxisAlignment.start,
      children: [

        Container(
          child: FutureBuilder(
           future: Provider.of<EatenMeals>(context, listen: false).getServerMeals(),
            builder: (ctx, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return Center(
                  child: CircularProgressIndicator(),
                );
              }

              return Consumer<EatenMeals>(
                builder: (ctx, mealsList, child) => ListView.builder(
                  itemCount: mealsList.eatenMeals.length,
                  itemBuilder: (ctx, index) =>
                      DailyEaten(mealsList.eatenMeals[index]),
                ),
              );
            },
          ),
        ),
      ],
    );
  }

如您所见,我的构建方法中没有任何内容,并且我已经使用 Consumer 来避免此循环,但构建方法仍然需要重建,您能用代码片段解释一下吗?我很感激