我有一个Riverpod Streamprovider,它可以管理如何将大量不同的Firebase文档呈现给用户。然后用户可以访问每个文档,进行一些更改,并返回到他们的文档列表。一旦他们进行了更改,该文档的行应该有一个勾号显示。唯一的问题是,这些文档在不同的集合中,每个都有自己的标识符。所以它不像仅仅流传输整个集合那么容易,我的函数需要获取每个项的标识符,然后获取要发送给用户的文档列表。
我有代码,所以它“只是工作”,但我不能弄清楚的是,为什么更新记录工作时,所有的代码都在提供程序内部,而当提供程序调用它的外部代码。例如,这个StreamProvider工作,我想要的和更新的文档被识别
final outputStreamProvider = StreamProvider.autoDispose((ref) async* {
final List<itemModelTest> itemList = [];
final user = ref.watch(loggedInUserProvider);
final uid = ref.watch(authStateProvider).value!.uid;
for (String ident in user.value!.idents) {
# get each item by its own identifier
final item = FirebaseFirestore.instance
.collection('items')
.where("ident", isEqualTo: ident)
.limit(1)
.snapshots();
final result = await item.first;
final test = result.docs[0];
final itemItem = itemModelTest.fromFirebaseQuery(test, uid);
itemList.add(itemItem);
# Listen for changes in the items
item.listen((event) async {
dev.log('event changed');
for (var change in event.docChanges) {
if (change.type == DocumentChangeType.modified) {
itemModelTest updatedModel =
itemModelTest.fromFirebaseQuery(test, uid);
itemList
.removeWhere((element) => element.title == updatedModel.title);
itemList.add(updatedModel);
}
}
});
}
yield itemList;
});
但是正如你所看到的,它包含了很多不属于那里的逻辑,而这些逻辑应该在我的firebase数据库类中,所以我试着将它拆分,现在在我的firebase crud类中,我有了几乎相同的代码:
Stream<List<itemModelTest>> itemsToReviewStream(LoggedInUser user, String uid) async*{
final List<itemModelTest> itemList = [];
for (String ident in user.idents) {
final item = FirebaseFirestore.instance
.collection('items')
.where("ident", isEqualTo: ident)
.limit(1)
.snapshots();
final result = await item.first;
final test = result.docs[0];
final itemItem = itemModelTest.fromFirebaseQuery(test, uid);
itemList.add(itemItem);
item.listen((event) async {
dev.log('event changed ${event.docChanges.first.doc}');
for(var change in event.docChanges){
if(change.type == DocumentChangeType.modified){
itemModelTest updatedModel = itemModelTest.fromFirebaseQuery(test, uid);
itemList.removeWhere((element) => element.title == updatedModel.title);
itemList.add(updatedModel);
}
}
});
}yield itemList;
}
我的StreamProvider现在看起来像这样
// Get a list of the currently logged in users papers to review
final testitemStreamProvider = StreamProvider.autoDispose((ref) {
final user = ref.watch(loggedInUserProvider).value;
final uid = ref.watch(authStateProvider).value!.uid;
return DataBase().itemsToReviewStream(user!, uid);
});
唯一的问题是使用第二种方法,firebase的更新不会触发用户界面的更新,所以当用户返回到他们的文档列表时,他们看不到哪些已经被处理过了。我一直在房子周围试图找出我做错了什么,但看不到。
编辑:只是一个快速编辑,以防万一,但这是为FlutterWeb,而不是iOS或Android
1条答案
按热度按时间fiei3ece1#
我离开这个以防其他人有同样的问题。这个项目的真实的问题是数据库结构不适合目的,进一步的限制是不要在数据库上重复数据。
最简单的解决方案(如果你碰巧阅读到这篇文章是因为你解决了一个类似的问题)是制作一个用户应该在他们自己的集合中访问的文档的副本,然后可以将其作为整个集合进行流传输。检查哪些文档已经和没有被用户查看总是要通过管理员帐户完成的,无论如何,所以这并不意味着会受到处罚。
为了管理我的特定数据存储库,我最终
1制作一个简单的提供程序来流式传输单个文档
然后,一旦您有了用户可以访问的所有文档的列表,就可以创建提供上述提供程序列表的提供程序
然后,您可以像平常一样在消费者中使用它,但它必须被“消费”两次。在我的例子中,我在ConsumerWidget的build方法中观察了ListProvider。它为您提供了各个页面的StreamProviders列表。最后,我使用ListView获取每个StreamProvide(listofProviders[index]),并使用provider展开它。当(...
然而,我不知道这种方法会变得多么脆弱!