【问题标题】:How to modify the state of a StateNotifier Provider from another provider in Riverpod?如何从 Riverpod 中的另一个提供者修改 StateNotifier 提供者的状态?
【发布时间】:2021-08-11 12:20:21
【问题描述】:

我对flutter和riverpod很陌生,所以如果问题不清楚,我很抱歉,如果是这样,请告诉我

我有 2 个提供者,一个监听 FireStore 集合的实时变化,另一个是 List Service,用于处理从 FireStore 接收到的项目的实际列表。我想将收到的列表添加到 itemList 中,然后通知监听 itemListProvider 的小部件,以便可以重建列表视图

项目列表状态通知提供者

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 的更改并根据当前状态重新创建列表

这不起作用,当对列表进行更改时,我的小部件不会重建。我相信它不起作用的原因是因为当我使用ref.watch(itemListProvider.notifier) 在我的“firestoreListUpdateWatcher”中创建“观察者”时,我创建了一个我的小部件没有监听的新实例,因此在发生更改时不会收到通知。这个假设正确吗?

另外,我怎样才能实现这种行为(从另一个提供者修改列表)

有没有更好的方法来设计我的应用来避免这种限制?

提前感谢您的帮助

【问题讨论】:

    标签: android firebase flutter riverpod


    【解决方案1】:

    正如您所说,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];
    }
    

    【讨论】:

    • 首先非常感谢您的回复!我尝试按照您建议的方式实施它,并且效果很好,我非常感谢您。在旁注中,我的方法是将业务逻辑与 UI 分离的合理方法吗?再次感谢!
    • 我认为没关系,它与您的 UI 解耦,您可以在其中实现其他功能而不会影响您的视图(按某些属性过滤等),您可以检查 MVVM 架构以为您创建不同的服务在不改变太多逻辑的情况下查看视图
    猜你喜欢
    • 2022-11-11
    • 2022-06-24
    • 2020-03-22
    • 2015-08-02
    • 1970-01-01
    • 2021-07-30
    • 2020-01-06
    • 2021-01-14
    • 1970-01-01
    相关资源
    最近更新 更多