【问题标题】:setState() or markNeedsBuild() called during build with Provider在使用 Provider 构建期间调用的 setState() 或 markNeedsBuild()
【发布时间】:2021-11-25 01:54:31
【问题描述】:

四处寻找,但找不到解决方案。在我的应用程序中,我调用 FutureBuilder 从 firebase 加载文档列表。虽然它有效,但我得到了setState() or markNeedsBuild() called during build.。你们对我如何摆脱这些错误有任何想法吗?

这是我的功能:

  Future<void> loadFollowers(List profilesId) async {

    loading = true;

    profilesId.forEach((id) async {
     final DocumentSnapshot doc = await userRef.doc(id).get();
     profile = Profile.fromDocument(doc);
    followersList.add(profile);
    });

   loading = false;

   notifyListeners();
 }

以及我在哪里得到错误:

@override
   Widget build(BuildContext context) {
    return Stack(
     children: [
      gradientBackground(),
      Scaffold(
        appBar: AppBar(
          brightness: Brightness.dark,
          elevation: 0,
          backgroundColor: Colors.transparent,
          centerTitle: true,
          title: Text('Seguidores',
              style:
                  TextStyle(color: Colors.white, fontFamily: 'MontSerrat')),
        ),
        backgroundColor: Colors.transparent,
        body: FutureBuilder(
          future: Provider.of<ProfileManager>(context, listen: false)
              .loadFollowers(widget.followersId),
          builder: (context, snapshot) {
            return Consumer<ProfileManager>(
              builder: (_, profileManager, __) {
                if (profileManager.loading)
                  return circularProgress(Colors.white);
                else
                  return ListView.builder(
                    itemCount: followersList.length,
                    itemBuilder: (context, index) {
                      //print(followersList[index].name);

                      return GestureDetector(
                        onTap: () {
                          Navigator.push(
                              context,
                              MaterialPageRoute(
                                  builder: (_) => ProfileScreen(
                                      /*posts: postManager
                                    .getPosts(profiles[index].id),*/
                                      home: false)));
                        },
                        child: Card(
                          margin: EdgeInsets.symmetric(
                              horizontal: 16, vertical: 8),
                          child: ListTile(
                            leading: CircleAvatar(
                              backgroundImage: CachedNetworkImageProvider(
                                  profileManager
                                          .followersList[index].picture ??
                                      ''),
                            ),
                            title: Text(
                              profileManager.followersList[index].name ??
                                  '',
                              style: TextStyle(
                                  fontFamily: 'BebasNeue', fontSize: 20),
                            ),
                          ),
                        ),
                      );
                    },
                  );
              },
            );
          },
        ))
      ],
    );
  }

【问题讨论】:

    标签: flutter flutter-provider


    【解决方案1】:

    试试这个

     Future<void> loadFollowers(List profilesId) async {
    
        loading = true;
    
        profilesId.forEach((id) async {
         final DocumentSnapshot doc = await userRef.doc(id).get();
         profile = Profile.fromDocument(doc);
        followersList.add(profile);
        });
    
       loading = false;
    
      WidgetsBinding.instance
            .addPostFrameCallback((_) => notifyListeners());
    
    
     }
    

    【讨论】:

      【解决方案2】:

      发生的事情是您的 FutureBuilder 正在调用 loadFollowers 方法,该方法将通知 profileManager 的侦听器。然后,您将使用将侦听 profileManager 的 Consumer 构建小部件。

      loadFollowers 结束时,FutureBuilder 将请求重建(因为它得到了它等待的未来),同时侦听器将调用 setState()。

      您的代码中还有另一个令人困惑的事情:您包含了一个 FutureBuilder 而不使用它(不等待未来或使用未来返回的数据),而是通过 profileManager 提供程序管理异步加载。你应该做一个或另一个。

      我建议你尝试删除 FutureBuilder。

      【讨论】:

        【解决方案3】:

        可能出了问题的是在 FutureBuilder 内部你返回了一个消费者。

        Consumer 用于查看正在调用的 Future loadFollowers 是否仍在加载。更好的方法是在一系列 if 语句中检查快照,如下所示:

        if (snapshot.hasData) {Do what you want to do when the Future is finished}
        else if (snapshot.hasError) {do some error handling, ${snapshot.error} contains the error}
        else {show a CircularProgressIndicator() because the Future has not returned anything yet.}
        

        要使其正常工作,您需要确保 Future 正在返回一些东西,例如 bool,因此将您的 Future 代码转换为:

        Future<bool> loadFollowers(List profilesId) async {
        
        loading = true;
        
        profilesId.forEach((id) async {
         final DocumentSnapshot doc = await userRef.doc(id).get();
         profile = Profile.fromDocument(doc);
        followersList.add(profile);
        });
        
        loading = false;
        
        notifyListeners();
        return true;
        }
        

        【讨论】:

          猜你喜欢
          • 2020-08-11
          • 2020-04-10
          • 2020-06-29
          • 2018-05-15
          • 2020-10-05
          • 2020-12-12
          • 2020-12-28
          • 2021-01-06
          相关资源
          最近更新 更多