Home > Software design >  How to run async function once in streambuilder
How to run async function once in streambuilder

Time:09-21

I have a streambuilder that Im trying to call a function that updates the read status on my app

void readMessage() async {
int num = 0;
final query = await FirebaseFirestore.instance
    .collection('chats')
    .doc(chatroomId(FirebaseAuth.instance.currentUser!.uid, widget.uid))
    .collection('messages')
    .where('uid', isEqualTo: widget.uid)
    .where('read', isEqualTo: false)
    .get();

query.docs.forEach((doc) {
  doc.reference.update({'read': true});
});

num = query.docs.length;

await FirebaseFirestore.instance
    .collection('users')
    .doc(FirebaseAuth.instance.currentUser!.uid)
    .update(
  {"messagesNotification": FieldValue.increment(-num)},
);
}

and in my streambuilder im trying

return Container(
      child: StreamBuilder(
        stream: FirebaseFirestore.instance
            .collection('chats')
            .doc(chatRoom)
            .collection('messages')
            .orderBy('createdAt', descending: true)
            .snapshots(),
        builder: (context,
            AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
          readMessage();

The issue is that it seems to be running twice, so if for example they have 3 unread messages its decreasing the message counter by 3 then 3 again. Im also not sure if this is how it works but am I right in believing that if a new message appeared in the stream it will run that method everytime so that incoming messages are marked as read when the stream is open?

CodePudding user response:

StreamBuilder widget rebuilds the ui with every change with the stream, so you need to wrap your readMessage() with conditional statement to decide whether to run this function or not

CodePudding user response:

You could create a boolean to check if the function is called

bool functionCalled = false;

Check if the function is called and if not you do your logic and inside it you set it to true. The next call won't jump in the if.

if(!functionCalled){
functionCalled = true;
int num = 0;
final query....
}
  • Related