Flutter Firebase:Firebase 中的数据更新,但未在屏幕上自动显示计数器更新

Posted

技术标签:

【中文标题】Flutter Firebase:Firebase 中的数据更新,但未在屏幕上自动显示计数器更新【英文标题】:Flutter Firebase: data updating in Firebase, but not showing the counter update on the screen automatically 【发布时间】:2021-06-19 15:02:39 【问题描述】:

我的 Firebase 中有一个计数器,用于保存一张图片的总投票数。当按下 upvote 按钮时,数据库应该将指定计数器的计数器更新 1,它会这样做。但是,它不会在应用程序屏幕上显示更新。例如,如果一张图片有 8 个赞,并且按下按钮进行赞,它仍然会在屏幕上显示 8 个赞,但在数据库中它现在将是 9 个赞。当我热刷新时,值会发生变化。我怎样才能让这两件事异步发生?我尝试过使用它,它总是更新数据库并且屏幕保持不变,或者屏幕改变并且数据库没有。

对于下面的函数,它们的行为符合预期,但在屏幕上不是异步的。

数据库中增加关注者的相关函数:

// likedposts is a list of posts that have already been liked and is initalised earlier
// even if I remove the if statement here, the behaviour is the same
void incrementFollowers(int index) async 
  if (!likedposts.contains(posts[index]))  
  likedposts.add(posts[index]);
  addLikedPost();
  FirebaseFirestore.instance
    .collection('uploads')
    .doc(usernames[index])
    .collection('images')
    .where('caption', isEqualTo: captions[index])
    .get()
    .then((querySnapshot) 
      querySnapshot.docs.forEach((result) async  
          FirebaseFirestore.instance
          .collection('uploads')
          .doc(usernames[index])
          .collection('images')
          .doc(result.id)
          .update('upvotes': upvotes[index]+1,);  
          setState(() 
            getUpvotes(index);
          );
      );
    );
   
  

显示赞成票的功能:

getUpvotes(int index) 
    return RichText(
      text: TextSpan(
          style:
              TextStyle(color: Colors.black, fontSize: 20.0),
          children: <TextSpan>[
          TextSpan(
          text: upvotes[index].toString() + ' upvotes',
          style: TextStyle(color: Colors.blue),
          recognizer: TapGestureRecognizer()
            ..onTap = () 
              print(
                  'This will take to upvoters of the photo');
            ),
      ]));
  

在我的应用中显示所有内容的小部件(要找到我调用 incrementFollowers 按钮的位置,只需对 incrementFollowers 执行 ctrl+F 即可找到它):

Widget _getPost() 
    
    Size size = MediaQuery.of(context).size;
    if (url!= null) 
    return new ListView.builder(
        itemCount: images.length,
        itemBuilder: (BuildContext context, int userIndex) 
          
          return Container(
            child: Column(
            
            children: <Widget>[
              Container(
                 
                //Includes dp + username + report flag
                margin: EdgeInsets.all(10),
                child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: <Widget>[
                    Row(
                      children: <Widget>[
                        Container(
                            margin: EdgeInsets.only(right: 8),
                            child: GestureDetector(
                                onTap: () 
                                Navigator.push(
                                  context, 
                                  MaterialPageRoute(
                                    builder: (context) => UserProfile(usernames[userIndex])
                                    ),
                                  );
                                ,
                                child: CircleAvatar(
                                  backgroundImage: displayPic[1],
                                ))),
                        RichText(
                          text: TextSpan(children: <TextSpan>[
                            TextSpan(
                                text: usernames[userIndex],
                                style: TextStyle(
                                    color: Colors.black, fontSize: 15.0),
                                recognizer: TapGestureRecognizer()
                                  ..onTap = () 
                                    Navigator.push(
                                      context, 
                                      MaterialPageRoute(
                                        builder: (context) => UserProfile(usernames[userIndex])
                                      ),
                                    );
                                  )
                          ]),
                        )
                      ],
                    ),
                    
                   IconButton(
                    icon: Image.asset('assets/pictures/ICON_flag.png'),
                    iconSize: 25,
                    onPressed: () 
                      reportUser(userIndex, context);
                
                    ,
                  ),
                  ],
                ),
              ),
              Stack(children: <Widget>[
                Container(
                    //the post picture
                    child: GestureDetector(
                      
                      //This is to handle the tagged users raised button
                      onTap: () 
                        if (isVisible == false)
                          setState(() 
                            isVisible = true;
                          );
                        else
                          setState(() 
                            isVisible = false;
                          );
                          
                      ,
                    ),
                    height: size.height * 0.5,
                    width: returnWidth(),
                  padding: EdgeInsets.only(
                    left: 16,
                    right: 16,
                    top: 0,
                    bottom: 24,
                  ),
                    // constraints: BoxConstraints(maxHeight: 50),
                   
                    decoration: BoxDecoration(
                      image: DecorationImage(
                         

                          fit: BoxFit.fill, image: NetworkImage(images[userIndex])),
                    )
                    
                    ),
                Positioned(
                  
                    top: 25,
                    left: 50,
                    child: returnTaggedUsers(userIndex),)
              ]),
              Row(
                mainAxisAlignment: returnAlignment(),
                // upvote + downvote + comment + send + save icons
                children: <Widget>[
                  Container(
                    color: upVoted ? Colors.blue : Colors.white,
                      margin: EdgeInsets.only(right: 8),
                      child: IconButton(
                        icon: Image.asset('assets/pictures/ICON_upvote.png'),
                        iconSize: 25,
                        onPressed: () async 
                          setState(() 
                            incrementFollowers(userIndex); 
                            
                          ); 
                          getUpvotes(userIndex);
                        ,
                      )

                  ),
                  Container(
                      color: downVoted ? Colors.blue : Colors.white,
                      margin: EdgeInsets.only(right: 8),
                      child: IconButton(
                        icon: Image.asset('assets/pictures/ICON_downvote.png'),
                        iconSize: 25,
                        onPressed: () 
                          setState(() 
                            
                            downVoted = true;
                            upVoted = false;                         
                          );
                        ,

                      )),
                  Container(
                      margin: EdgeInsets.only(right: 8),
                      child: IconButton(
                        icon: Image.asset('assets/pictures/ICON_comment.png'),
                        iconSize: 25,
                        onPressed: () 
                         commentPopUp(userIndex, context);
                        ,
                      )),
                  Container(
                      margin: EdgeInsets.only(right: 8),
                      child: IconButton(
                        icon: Image.asset('assets/pictures/ICON-send.png'),
                        iconSize: 25,
                        onPressed: () 
                          print(
                              'This will let a user send the post to another user');
                        ,
                      )),
                  Container(
                      margin: EdgeInsets.only(right: 8),
                      child: IconButton(
                        icon: Image.asset('assets/pictures/ICON_save.png'),
                        iconSize: 25,
                        onPressed: () 
                          Navigator.push(
                            context, 
                            MaterialPageRoute(
                              builder: (context) => ReportPanel()
                              ),
                            );
                        ,
                      )),
                      
                ],
              ),
              Column(
                mainAxisAlignment: returnAlignment(),
                //This column contains username, upload description and total upvotes
                children: <Widget>[
                  Container(
                    
                    //The person who posted along with photo description
                    alignment: returnCommentAlignment(),
                    margin: EdgeInsets.only(left: 10, right: 10),
                    child: RichText(
                        text: TextSpan(
                            style:
                                TextStyle(color: Colors.black, fontSize: 20.0),
                            children: <TextSpan>[
                          TextSpan(
                              text: usernames[userIndex] + ': ',
                              style: TextStyle(color: Colors.blue),
                              recognizer: TapGestureRecognizer()
                                ..onTap = () 
                                  Navigator.push(
                                      context, 
                                      MaterialPageRoute(
                                        builder: (context) => UserProfile(usernames[userIndex])
                                      ),
                                    );
                                ),
                          TextSpan(text: captions[userIndex]),
                        ])),
                  ),
                  Container(
                    //The total upvotes of post
                    alignment: returnCommentAlignment(),
                    margin: EdgeInsets.only(left: 10, right: 10),
                    child: getUpvotes(userIndex), 
                  )
                ],
              ),
              Column(
                mainAxisAlignment: returnAlignment(),
                //This column contains username and comment of commenters
                children: <Widget>[
                  Container(
                    //First comment
                    alignment: returnCommentAlignment(),
                    margin: EdgeInsets.only(left: 10, right: 10),
                    child: RichText(
                        text: TextSpan(
                            style:
                                TextStyle(color: Colors.black, fontSize: 20.0),
                            children: <TextSpan>[
                          TextSpan(
                              text:
                                  'HarperEvans1: ', //will be a username from firebase
                              style: TextStyle(color: Colors.blue),
                              recognizer: TapGestureRecognizer()
                                ..onTap = () 
                                  print(
                                      'This will take to profile of that person');
                                ),
                          TextSpan(text: 'Nice photo!'),
                        ])),
                  ),
                  Container(
                    //Second comment
                    alignment: returnCommentAlignment(),
                    margin: EdgeInsets.only(left: 10, right: 10),
                    child: RichText(
                        text: TextSpan(
                            style:
                                TextStyle(color: Colors.black, fontSize: 20.0),
                            children: <TextSpan>[
                          TextSpan(
                              text:
                                  'trevorwilkinson: ', //will be a username from firebase
                              style: TextStyle(color: Colors.blue),
                              recognizer: TapGestureRecognizer()
                                ..onTap = () 
                                  print(
                                      'This will take to profile of that person');
                                ),
                          TextSpan(
                              text:
                                  'Panda Panda Panda Panda Panda Panda Panda Panda Panda Panda Panda Panda Panda Panda'),
                        ])),
                  ),
                  Container(
                    //view more comments
                    alignment: returnCommentAlignment(),
                    margin: EdgeInsets.only(left: 10, right: 10),
                    child: RichText(
                        text: TextSpan(
                            style:
                                TextStyle(color: Colors.grey, fontSize: 20.0),
                            children: <TextSpan>[
                          TextSpan(
                              text:
                                  'view more comments', //will take to the comments
                              style: TextStyle(color: Colors.grey),
                              recognizer: TapGestureRecognizer()
                                ..onTap = () 
                                  Navigator.push(
                                  context, 
                                  MaterialPageRoute(
                                    builder: (context) => CommentPage(posts[userIndex], usernames[userIndex])
                                    ),
                                  );
                                ),
                        ])),
                  )
                ],
              )
            ],
          ));
        );
    
  

谢谢!

【问题讨论】:

【参考方案1】:

目前,您没有任何东西可以触发 Firebase 的重建。您需要在 getUpvotes 函数中返回 FutureBuilderStreamBuilder。这将收到有关云中更改的通知并触发重新构建。

这里有一些东西可以帮助您入门。而是在您的 getUpvotes 方法中返回它并完成 StreamBuilder 的流部分

StreamBuilder(
    stream: Firestore.instance.collection...// finish this part to get your snapshot of total upvotes from your collection,
    builder: (context, snapshot) 
         if(snapshot.hasData) 
     return RichText(
      text: TextSpan(
        style: TextStyle(color: Colors.black, fontSize: 20.0),
        children: <TextSpan>[
          TextSpan(
              text: upvotes[index].toString() + ' upvotes',
              style: TextStyle(color: Colors.blue),
              recognizer: TapGestureRecognizer()
                ..onTap = () 
                  print('This will take to upvoters of the photo');
                ),
               ],
             ),
          );
         
   else 
    // handle no data
   
 ,
);

【讨论】:

您好,感谢您的评论。所以我试着按照你说的做,但是行为仍然是一样的;数据库更新,但屏幕不会直到我热刷新或者我进入另一个页面并返回它。这是我在流中添加的内容:流:FirebaseFirestore.instance.collection('uploads') .doc(usernames[index]).collection('images').snapshots(),但它仍然不会异步更新小部件。我做错什么了吗?提前致谢 刚刚注意到一些更奇怪的行为。如果您查看我上面的 incrementFollowers 函数,您会看到以下行:.update('upvotes': upvotes[index]+1,); 。这使得数据库更新,但小部件没有。但如果我这样做:.update('upvotes': upvotes[index]++,); ,小部件会正确更新,但数据库不会。不知道为什么会这样 玩弄了你的解决方案,我明白了。非常感谢!

以上是关于Flutter Firebase:Firebase 中的数据更新,但未在屏幕上自动显示计数器更新的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 和 Firebase:任务 ':firebase_auth:compileDebugJavaWithJavac' 执行失败

Flutter - 将 Firebase 通知推送给没有 Firebase 身份验证的特定用户

Flutter 和 Firebase:从 Firebase 中的数组中删除项目(地图)

Flutter : getDownloadUrl (firebase 存储)

Flutter WEB:Firebase:没有创建 Firebase 应用“[DEFAULT]”

未捕获的 ReferenceError:Flutter 中未定义 firebase