Riverpod:重新计算一个提供接收更新的项目列表的提供者

Riverpod: Recompute a provider providing a list of items on receiving updates

我有一个简单的用例,我正在尝试重新计算一个提供项目列表的提供者,如下所示:

final itemProvider = StateProvider<Item>((ref) {
    return Item() ;
});

final itemListProvider = Provider<List<Item>>((ref) {
 watch(itemProvider);
...//do something to compute new list
 return computedList ;
});

我希望 itemListProvider 在 itemProvider 的状态从外部更改时自动重新计算,以便 itemListProvider 继续将新项目添加到它提供的现有列表中。 有没有办法使用 Riverpod 以上述特定方式实现这一点? 我知道我可以使用 StateNotifierProvider 或 StateProvider 并使用状态分配调用更新 itemList,但我期待以被动方式进行。

感谢任何帮助或指导。谢谢!

这可以通过单个 StateNotifierProvider 轻松完成。

class ItemList extends StateNotifier<List<Item>> {
  ItemList() : super([]);

  static final provider = StateNotifierProvider<ItemList, List<Item>>((ref) => ItemList());

  Item _current = Item();
  Item get current => _current;

  void addItem(Item item) {
    _current = item;
    state = [...state, item];
  }
}

用法:

// Add an item, which updates the current item
watch(ItemList.provider.notifier).addItem(item);

// Get the current item
final currentItem = watch(ItemList.provider.notifier).current;

// Get the List<Item> from state
final itemList = watch(ItemList.provider);

如果您真的想要避免使用 StateNotifierProvider,您可以执行以下操作,但我强烈建议您使用第一种方法。不管怎样:

final itemProvider = StateProvider<Item>((ref) => Item());

final itemListProvider = StateProvider<List<Item>>((ref) => []);

final computedListProvider = Provider<List<Item>>((ref) {
  final item = ref.watch(itemProvider);
  final itemList = ref.watch(itemListProvider);
  WidgetsBinding.instance?.addPostFrameCallback((_) {
    if (itemList.state.contains(item.state)) return;
    itemList.state = [...itemList.state, item.state];
  });

  return itemList.state;
});

最佳方法是

  1. 对于应作为提供程序的一部分进行评估的任何输入参数,您可以使用 riverPod .family。 Link 这里 (https://riverpod.dev/docs/concepts/modifiers/family/)

  2. 或者根据文档,如果更新了 itemProvider,itemListProvider 应该得到 re-evaluated。如果它不适合您的用例,那么在您的小部件中,您可以调用 ref.refresh 到 re-evaluate 提供者。对于 Refresh 执行如下所示并将您的提供者更改为 FutureProvider

    未来 _refresh(){ ref.refresh(itemListProvider); return ref.read(itemListProvider.future); }