Firestore 和 flutter:使用流优化数据读取
Firestore and flutter : Optimize data reads with streams
说明
我使用 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 }
如果你想在查询服务器之前先从客户端本地缓存中读取,你可以这样做以避免读取。只需指定一个 source option to query the cache first, then if it's not there, query the server. Read more about Firestore persistence.
说明
我使用 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 }
如果你想在查询服务器之前先从客户端本地缓存中读取,你可以这样做以避免读取。只需指定一个 source option to query the cache first, then if it's not there, query the server. Read more about Firestore persistence.