0
votes

Hello i am working with fire store database for making one to one chat between user. Here i want some pagination of messages. So i called snapshot listener inside initState So the problem is while i navigate to chat screen, initState called snapshot listener DocumentType.added automatically. so data becomes duplicate..

here is my code which i called inside initState

List<DocumentSnapshot> _products = [];
StreamController<List<DocumentSnapshot>> _streamController =
StreamController<List<DocumentSnapshot>>.broadcast();

@override
void initState() {
     db
    .collection('chat')
   .document(docId)
    .collection('messages')
    .orderBy('timestamp', descending: true)
    .snapshots().listen((data) => onChangeData(
          data.documentChanges,
        ));
}
void onChangeData(
  List<DocumentChange> documentChanges,
) {
  documentChanges.forEach((productChange) {
    if (productChange.type == DocumentChangeType.removed) {
      _products.removeWhere((product) {
        return productChange.document.documentID == product.documentID;
      });

      _streamController.add(_products);
    }
    if (productChange.type == DocumentChangeType.added) {
    _products.insert(productChange.newIndex, productChange.document);
      _streamController.add(_products);
    }
    if (productChange.type == DocumentChangeType.modified) {
      int indexWhere = _products.indexWhere((product) {
        return productChange.document.documentID == product.documentID;
      });

      if (indexWhere >= 0) {
        _products[indexWhere] = productChange.document;
      }

      _streamController.add(_products);   
    }
  });
}
1
You are passing a List of document changes into the onChangeData method. Is this a list you have previously filtered between the data your had locally and the new data coming from Firestore? You mention that this is a 1 to 1 chat, but your variables are _products are these the messages?João Soares
Clear your list on the top and then addBloodLoss
@João Soares sorry for the bad variable declaration..the products is List<Documentsnapshot>_productsSourav Das
@BloodLoss can please show me a demoSourav Das
@SouravDas Can you please answer my first question. "You are passing a List of document changes into the onChangeData method. Is this a list you have previously filtered between the data your had locally and the new data coming from Firestore?"João Soares

1 Answers

1
votes

This is normal behavior - when you attach a listener to a document or a collection, you first get a callback with the current data, and then subsequent calls whenever the data is changed.

Because you are using pagination, and attaching a new listener within initState of each of the pages, you get that first callback on each page change.

What you should do is create a separate class that is responsible for listening to your collection and notifying any widgets that should be updated. You can use the state management library of your choice for notifying the widgets of data changes.