Firestore 和 Flutter:使用流优化数据读取

Posted

技术标签:

【中文标题】Firestore 和 Flutter:使用流优化数据读取【英文标题】:Firestore and flutter : Optimize data reads with streams 【发布时间】:2020-10-20 01:53:09 【问题描述】:

说明

我使用 BLoC 逻辑来收听我的流,我想尽量减少数据读取。

我知道 QuerySnapshot 会跟踪以前的文档,如果文档没有更改,则会从缓存中挑选。

问题是快照不包含有关用户个人资料图片、姓名等的信息,我必须使用 getInfoFromId() 获取这些信息,我想找到一种方法不使用此函数 一个用户被更改、删除或添加时的每个用户

  Stream<List<FeedUser>> rolesToStream(String newsId) 
return Firestore.instance
    .collection('pages')
    .document(newsId).collection('users')
    .snapshots()
    .map(
        (snapshot)
      return snapshot.documents.map(
              (document)
            FeedUser user = FeedUser();
            user.fromSnapshot(document);
            user.contact = getInfoFromId(user.id);
            // The contact infos of a user is a future because we have to get it elsewhere, in a Firebase (NOT FIRESTORE) database. It theorically shouldn't be read after being read once after the event "RoleLoadMembers" 
            // Then we retrieve the contact infos after it is retrieved
            user.contact.then(
                    (contact)
                  user.retrievedContact = contact;
                
            );
            return user;
          
      ).toList();
    
);

这是我的 BLoC 监听数据的方式

  Stream<RoleState> _mapRolesToState() async* 
subscription?.cancel();
subscription =
    _feedRepository.rolesToStream(globalNews.feedId).listen((data) 
  add(RoleUpdated(data));
);

这就是我如何改变我的角色

  void changeRole(String idFeed,String userId, AppRole role)
collectionReference
    .document(idFeed)
    .collection('users')
    .document(userId)
    .updateData(
  'role':EnumToString.parse(role),
);

我的问题如下:每当我更改用户的角色时,其他所有用户都会被流重新读取,我不知道如何解决它。 提前感谢您的帮助。


状态日志

可能的状态:

RoleLoadingMembers 角色加载成功 RoleLoadingFailure(从未发生过)

可能发生的事件:

RoleLoadMembers 角色更新 更改角色 删除成员 添加成员

这是第一次加载后的日志:

I/flutter (27792): RoleLoadMembers
I/flutter (27792): Reading infos of the user : E4nT23Ohi0Za7JIQDaQ7Ohwe7Rn1
I/flutter (27792): Reading infos of the user : Svbj4tAIhIRcjQNqvYYsLSDXxwu2
I/flutter (27792): Reading infos of the user : cBm2KG6rEAbiaLGMAC08bvefNSn1
I/flutter (27792): RoleUpdated
I/flutter (27792): Transition  currentState: RoleMembersLoading, event: RoleUpdated, nextState: RoleLoadingSuccess 

在换了角色之后:

I/flutter (27792): ChangeRole
I/flutter (27792): Reading infos of the user : E4nT23Ohi0Za7JIQDaQ7Ohwe7Rn1
I/flutter (27792): Reading infos of the user : Svbj4tAIhIRcjQNqvYYsLSDXxwu2
I/flutter (27792): Reading infos of the user : cBm2KG6rEAbiaLGMAC08bvefNSn1
I/flutter (27792): RoleUpdated
I/flutter (27792): Transition  currentState: RoleLoadingSuccess, event: RoleUpdated, nextState: RoleLoadingSuccess 

删除成员后(正确删除了成员但仍读取数据库中的信息):

I/flutter (27792): RemoveMember
I/flutter (27792): Reading infos of the user : E4nT23Ohi0Za7JIQDaQ7Ohwe7Rn1
I/flutter (27792): Reading infos of the user : Svbj4tAIhIRcjQNqvYYsLSDXxwu2
I/flutter (27792): RoleUpdated
I/flutter (27792): Transition  currentState: RoleLoadingSuccess, event: RoleUpdated, nextState: RoleLoadingSuccess 

【问题讨论】:

如果您不想重新阅读已经阅读过的文档,您可以实现自己的客户端缓存。 我把它作为最后的手段,因为我从来没有这样做过,但我会试一试,学习永远不会有坏处:)!祝你有美好的一天 【参考方案1】:

如果您想在查询服务器之前先从客户端本地缓存中读取,您可以这样做以避免读取。只需指定source option 先查询缓存,如果不存在,则查询服务器。阅读有关Firestore persistence 的更多信息。

【讨论】:

以上是关于Firestore 和 Flutter:使用流优化数据读取的主要内容,如果未能解决你的问题,请参考以下文章

Flutter:使用来自 Firestore 的多集合流创建动态更新的 DataTable

Flutter 将两个 Firestore 流合并为一个流

将用户 uid 传递给 Flutter 中的 Firestore 流查询

Flutter/Firestore - 在流构建器中的动态列表视图上实现“分页”

Flutter 如何优化 Firestore 存储读取以防止大量不必要的读取

FLUTTER,FIRESTORE:我有一个流构建器,它从集合中的所有文档中返回某个字段..如何添加查询?