firebaseflutterfirebase-realtime-databasedartchat

Flutter : how to get newly added record from firebase real time database?


I'm using below code to retrieve all the data from my firebase chat room

void readDataFromFireBase() {

    var databaseReference =
        FirebaseDatabase.instance.reference().child("messages");

    databaseReference
        .child(chatroom.chatId)
        .once()
        .then((DataSnapshot snapshot) {
      Map<dynamic, dynamic> values = snapshot.value;

      values.forEach((key, value) {
        setState(() {
          chatMessageList.add(ChatMessage(
              value["message"], value["fromUser"], value["timestamp"]));
          chatMessageList.sort((a, b) {
            var formatter = new DateFormat('MM/dd/yyyy, kk:mm');
            var dateOne = formatter.parse(a.timestamp);
            var selectedDate = formatter.parse(b.timestamp);
            return dateOne.compareTo(selectedDate);
          });


      });
    });
  }

now how can i get notify my chat room when the new message has arrived

currently i'm using below code to listen child added event

listenDataFromFireBase() {
    var db = FirebaseDatabase.instance.reference().child("messages");
    db.child(chatroom.chatId).onChildAdded.listen((data) {
      print("GET_NEW_DATA");
      print(data.snapshot.value["message"] ?? '');
      print(data.snapshot.value["fromUser"] ?? false);
      print(data.snapshot.value["timestamp"] ?? '');
    });
  }

but there is one issue i'm facing this listenDataFromFireBase() load all the the data from particular room

My requirement is whenever new message added in chatroom i want to animate my message layout

How can i get notify my screen whenever new message will add in my chat room.

If need more information please do let me know. Thanks in advance. Your efforts will be appreciated.


Solution

  • As you've discovered onChildAdded fires immediately for any existing data, and after that also when any data is added. If you want to distinguish between these two cases, you'll need to combine an onChild listener and an onValue listener.

    In the onValue listener, all you do is flag whether that event has happened:

    databaseReference.onValue.listen((event) {
      setState(() { 
        isInitialDataLoaded = true
      });
    });
    

    Now do all your data processing in the onChildAdded listener, getting the message from the snapshot and adding it to the list. Then use the isInitialDataLoaded to detect whether this is initial data, or an update:

    var db = FirebaseDatabase.instance.reference().child("messages");
    db.child(chatroom.chatId).onChildAdded.listen((data) {
      // TODO: get message from snapshot and add to list
    
      if (isInitialDataLoaded) {
        // TODO: alert the view about the new data
      }
    });
    

    So you'll have two listeners on the same node. The Firebase SDK actually detects this situation and only reads the data from the server once, so there is no extra data being transferred in this case.