android - 如何从 Riverpod 中的另一个提供者修改 StateNotifier 提供者的状态?
问题描述
我对flutter和riverpod很陌生,所以如果问题不清楚,我很抱歉,如果是这样,请告诉我
我有 2 个提供者,一个监听 FireStore 集合的实时变化,另一个是 List Service,用于处理从 FireStore 接收到的项目的实际列表。我想将收到的列表添加到 itemList 中,然后通知监听 itemListProvider 的小部件,以便可以重建 listview
项目列表状态通知提供程序
final itemListProvider =
StateNotifierProvider<ItemListService, List<Item>>(
(ref) => ItemListService([]));
实时监听器
final firestoreListUpdateWatcher = Provider((ref) {
//Listens to a stream which provide query snapshot, this works as intended
final firestoreListWatcher = ref.watch(firestoreListProvider);
//using `ref.watch(itemListProvider.notifier)` because i want to be able
//to change the state from this provider
final itemListProvider = ref.watch(itemListProvider.notifier);
firestoreLisUpdateWatcher.when(
data: (value) {
for (int i = 0; i < value.docChanges.length; i++) {
QueryDocumentSnapshot currentQuery = value.docs[i];
//current item in list
ListItem item = fireStoreList.fromMap(currentQuery.data());
//add current item to the ListService
itemListProvider.add(item);
}
},
loading: () {},
error: (err, stack) {});
});
项目列表服务类
class ItemListService extends StateNotifier<List<Item>> {
ItemListService(List<Item> itemList):super(itemListList ?? []);
void add(Item it) {
state = [...state, it];
}
//more methods modifying the list....
}
在我的小部件的构建功能中,我只想听对 itemListProvider 的更改并根据当前状态重新创建列表
这不起作用,当对列表进行更改时,我的小部件不会重建。我相信它不起作用的原因是因为当我在我的“firestoreListUpdateWatcher”中创建“观察者”时,使用ref.watch(itemListProvider.notifier)
我创建一个新实例,我的小部件没有在监听,因此在发生更改时不会收到通知。这个假设正确吗?
另外,我怎样才能实现这种行为(从另一个提供者修改列表)
有没有更好的方法来设计我的应用程序来避免这种限制?
在此先感谢您的帮助
解决方案
正如您所说,ref.watch 正在重新创建提供程序,这就是为什么您没有看到您的更改,您可以使用当前逻辑执行的操作是查看流而不是提供程序,并使用相同的侦听器更新状态itemListProvider 不创建另一个 Provider:
/// This is your StateNotifierProvider
final itemListProvider = StateNotifierProvider.autoDispose<ItemListService, List<Item>>((ref) {
//Listen to the stream itself instead of the value hold by the provider
final firestoreListStream = ref.watch(firestoreListProvider.stream);
//Create the instance of your StateNotifier
final itemListProvider = ItemListService([]);
/// subscribe to the stream to change the state accordingly
final subscription = firestoreListStream.listen((value) {
for (int i = 0; i < value.docChanges.length; i++) {
QueryDocumentSnapshot currentQuery = value.docs[i];
//current item in list
ListItem item = fireStoreList.fromMap(currentQuery.data());
//add current item to the ListService
itemListProvider.add(item);
}
});
/// When you stop using this porvider cancel the subscription to the stream, to avoid memory leaks
ref.onDispose(subscription.cancel);
return itemListProvider;
});
有了这个,您将不需要另一个 Provider ( firestoreListUpdateWatcher
)
作为建议,我注意到您遍历 for 循环并单独添加它们,这将强制状态更新多次,我建议先获取列表,然后使用 addAll 方法更新状态
final subscription = firestoreListStream.listen((value) {
List<ListItem> items = [];
for (int i = 0; i < value.docChanges.length; i++) {
QueryDocumentSnapshot currentQuery = value.docs[i];
//current item in list
ListItem item = fireStoreList.fromMap(currentQuery.data());
//add current item to the ListService
items.add(item);
}
ItemListService.addAll(items);
});
并在您的 ItemsService 中创建 addAll 方法
void addAll(Iterable<Item> it) {
state = [...state, ...it];
}
推荐阅读
- python - 从opencv生成的图像(没有numpy)上的给定两个点没有正确计算坡度角度
- java - 如何确保 gradle 仅在将应用程序构建到 100% 后才执行主类?
- rstudio - 在计算发育迟缓患病率置信区间时,我必须考虑哪些变量?
- c# - 如何在标签c#中以windows窗体显示数据库表的所有列
- android - 我能知道 .txt 文件在“context.openFileInput("txt")”中的位置吗
- scala - 使用 fs2 将 URL 流式传输到本地文件
- css - 页面重新加载后,Django保持下拉选择的语言
- python - 如果列中超过 90% 的值为 0,则删除 Dataframe 中的列
- c - 如果我正在制作文件路径,哪些应该更快?
- php - HTML Select 值属性拆分结果到多个字符串