Flutter中的Firestore快照侦听器数据重复问题

Posted

技术标签:

【中文标题】Flutter中的Firestore快照侦听器数据重复问题【英文标题】:Firestore snapshot listener data duplication issue in flutter 【发布时间】:2020-01-24 18:44:18 【问题描述】:

您好,我正在使用 Fire Store 数据库在用户之间进行一对一聊天。在这里,我想要一些消息的分页。所以我在 initState 中调用了快照监听器所以问题是当我导航到聊天屏幕时,initState 自动调用了快照监听器 DocumentType.add。所以数据变得重复..

这是我在 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);   
    
  );

【问题讨论】:

您正在将文档更改列表传递给onChangeData 方法。这是您之前在本地数据和来自Firestore 的新数据之间过滤的列表吗?你提到这是一对一的聊天,但你的变量是_products 这些是消息吗? Clear您的列表在顶部,然后是add @João Soares 对错误的变量声明感到抱歉。产品是 List_products @BloodLoss 可以给我演示一下 @SouravDas 你能回答我的第一个问题吗? “您将文档更改列表传递给 onChangeData 方法。这是您之前在本地数据和来自 Firestore 的新数据之间过滤的列表吗?” 【参考方案1】:

这是正常行为 - 当您将侦听器附加到文档或集合时,您首先会收到包含当前数据的回调,然后在数据更改时进行后续调用。

因为您正在使用分页,并且在每个页面的 initState 中附加了一个新侦听器,所以您会在每次页面更改时获得第一个回调。

你应该做的是创建一个单独的类,负责监听你的集合并通知任何应该更新的小部件。您可以使用您选择的状态管理库来通知小部件数据更改。

【讨论】:

坦率地说,不,因为我上面描述的内容没有任何困难。简直太费时间了,我没时间。此外,SO 不是让其他人编写您的代码,它是为了让您可以找到您不知道答案的问题的答案。我认为我已经用简单的语言非常清楚地解释了您遇到问题的原因以及解决方法。 实际上我知道如何使用 Bloc 或 provider 之类的状态管理,但问题是需要从某个地方调用 onchange 监听器,我对此感到困惑...... 因此,例如,如果您使用 Provider,您将创建一个扩展 ChangeNotifier 的类。此类将附加 Firestore 侦听器,该侦听器依次调用您的 onChangeData 函数,该函数又更新 _products 并在适当时调用 notifyListeners()。您将只有 1 个此 ChangeNotifier 实例,通过 Provider 公开。现在,您的每个页面只需要在 build() 方法中的某处调用 Provider.of&lt;YourChangeNotifier&gt;(context),以便在调用 notifyListeners() 时重新构建。 所以你从 changenotifier 类中调用了 onchange 监听器...怎么做 您将 onChangeData 函数与 _products 以及您在其中的任何其他内容一起移动到 ChangeNotifier...

以上是关于Flutter中的Firestore快照侦听器数据重复问题的主要内容,如果未能解决你的问题,请参考以下文章

区分 Firestore 中的第一次查询快照和更改侦听器

Flutter:Firebase 身份验证和 Firestore 快照流

Firestore 分页数据 + 快照监听器

Flutter - 使用提供程序包侦听 Firebase 用户的用户配置文件(Firestore)中的数据更改

如何从 Vuex 商店中删除 Firestore 快照侦听器

可以从 Firestore 快照 Flutter 中获取元数据吗?