Home > database >  FirebaseList in Flutter duplicates all values
FirebaseList in Flutter duplicates all values

Time:12-05

I think I'm misunderstanding how the FirebaseList widget in Flutter is working.

I'm using Firebase Realtime Database for the chat feature in my app with this data:

{
    "chatMessageOne": {...},
}

Here is how I'm using the widget:

  List<ChatMessage> chatMessages = [];

  @override
  void initState() {
    // dbRef = dbInstance.ref("/events/${widget.event.event.eventId}");
    dbRef = dbInstance.ref("/events/");
    var query = dbRef!.child(widget.event.event.eventId);
    FirebaseList(
      query: query,
      onChildAdded: (index, snapshot) {
        Map<dynamic, dynamic> childMap = snapshot.value as dynamic;
        ChatMessage newChatMessage = ChatMessage(
          chatMessageId: snapshot.key.toString(),
          userId: childMap["userId"],
          displayName: childMap["displayName"],
          message: childMap["message"],
          datetime: childMap["datetime"],
        );

        chatMessages.add(newChatMessage);
        print("onChildAdded:chatMessages: $chatMessages"); // prints [Instance of 'ChatMessage']
      },
      onValue: (snapshot) {
        for (var child in snapshot.children) {
          Map<dynamic, dynamic> childMap = child.value as dynamic;
          ChatMessage newChatMessage = ChatMessage(
            chatMessageId: child.key.toString(),
            userId: childMap["userId"],
            displayName: childMap["displayName"],
            message: childMap["message"],
            datetime: childMap["datetime"],
          );

          chatMessages.add(newChatMessage);
        }
        print("onValue:chatMessages: $chatMessages"); // prints [Instance of 'ChatMessage', Instance of 'ChatMessage']
      },
    );

    _messageFieldController = TextEditingController();
    super.initState();
  }

I'm then using a ListView Builder in my build method to display all the messages. For some reason, nothing displays when the screen first opens but chatMessages list has data that you can see from the print statements. If I hot reload (not resetting state) the screen two messages (the same one duplicated twice) will be displayed despite there only being one message in the database. Additionally, if I send a message then it seems to retrieve all the messages in the database and display them all at once instead of just the new one...

CodePudding user response:

With the code you shared you'll indeed see all messages twice:

  • onChildAdded gets called for each child node under query right away, and then whenever a new node is added.
  • onValue gets called with existing child node under query right away, and then whenever there is any change to that data. If you implement this method, you'll also want to clear chatMessages each time onValue gets called - as it always gets a snapshot with all messages, not just the changes.

So you should implement one or the other, not both.

  • Related