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

Flutter Firebase: data updating in Firebase, but not showing the counter update on the screen automatically

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

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

增加数据库中followers的相关函数:

// 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])
                                    ),
                                  );
                                }),
                        ])),
                  )
                ],
              )
            ],
          ));
        });
    }
  }

谢谢!

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

这里有一些可以帮助您入门的东西。 Return 改为在您的 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
   }
 },
);