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 underquery
right away, and then whenever a new node is added.onValue
gets called with existing child node underquery
right away, and then whenever there is any change to that data. If you implement this method, you'll also want to clearchatMessages
each timeonValue
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.