簡體   English   中英

Riverpod StateNotifierProvider 依賴於 FutureProvider

[英]Riverpod StateNotifierProvider depend on a FutureProvider

我有一個依賴於StateNotifierProviderFutureProvider 目前它們看起來像下面這樣。

final catalogProvider = StateNotifierProvider<CatalogNotifier, CatalogState>((ref) {
  final network = ref.watch(networkProvider.future); // future provider

  return CatalogNotifier(network: network);
});

這使我的CatalogNotifier接受Future<NetworkProvider>而不是NetworkProvider並要求我執行如下操作。

await (await.network).doGet(...)

避免等待多個並允許CatalogNotifier接受裸網絡提供者的最佳方法是什么,這樣我就可以像NetworkProvider await.network.doGet(...)這樣寫?


為了完整起見,以下是其他相關供應商

final networkProvider = FutureProvider<Network>((ref) async {
  final cache = await ref.watch(cacheProvider.future);
  return Network(cacheManager: cache);
});
final cacheProvider = FutureProvider<CacheManager>((ref) async {
  final info = await ref.watch(packageInfoProvider.future);

  final key = 'cache-${info.buildNumber}';

  return CacheManager(Config(
    key,
    stalePeriod: const Duration(days: 30),
    maxNrOfCacheObjects: 100,
  ));

我確定我可以將我的緩存提供程序作為未來進入 .network 提供程序,因此它不必是FutureProvider ,但我對如何解決上述問題很感興趣,因為在另一種情況下,如果我取決於 3 或 4 個FutureProvider s,這可能不是一個選項。

使用 riverpod v2 及其代碼生成功能,這變得容易得多,因為您不再需要決定提供程序的類型。 (除非你要)

riverpod 2 中的 StateNotifier


@riverpod
Future<CatalogController> catalog(CatalogRef ref) async {
  final network = await ref.watch(networkProvider.future);

  return CatalogController(network: network);
}

Riverpod 2 中的替代方法

您經常希望計算一個值並有一種方法可以從 UI 中顯式重做該計算。 類似於來自.network 的列表,但在 UI 中有一個刷新按鈕。 這可以在 riverpod 2 中建模如下。

@riverpod
Future<CatalogState> myFeed(MyFeedRef ref) async {
  final json = await loadData('url');

  return CatalogState(json);
}

// and when you want to refresh this from your UI, or from another provider
ref.invalidate(myFeedProvider);

// if you want to also get the new value in that location right after refreshing
final newValue = await ref.refresh(myFeedProvider);

Riverpod 2 還具有提供程序的加載和錯誤屬性。 您可以使用這些來相應地顯示 UI。 雖然如果你想在你的提要加載時或在錯誤 state 中顯示提供者的最后結果,你必須自己使用返回流/BehaviorSubject 的提供者 model,緩存最后一個值等。

這使我的 CatalogNotifier 接受 Future 而不是 >NetworkProvider 並要求我執行以下操作。

我想不出一種方法來獲得你想要的結果。

你不能只接受一個 AsyncValue 並在 statenotifier 中處理它嗎?

final catalogProvider = StateNotifierProvider<CatalogNotifier, CatalogState>((ref) {
      final network = ref.watch(networkProvider); // future provider
    
      return CatalogNotifier(network: network);
    });

那么你也能:

void someFunction() async {
  network.maybeWhen(
    data: (network) => AsyncData(await network.doGet(...)), 
    orElse: () => state = AsyncLoading(),
);
}

你可以讓 AsyncValue 成為 StateNotifier 的子類型,我以 Todo 列表為例。

如下:

class TodoNotifier extends StateNotifier<AsyncValue<List<Todo>>> {

  TodoNotifier(this._ref) : super(const AsyncValue.loading()) {
    _fetchData();
  }

  final Ref _ref;

  Future<void> _fetchData() async {
    state = const AsyncValue.loading();
    // todoListProvider is of type FutureProvider
    _ref.read(todoListProvider).when(data: (data) {
      state = AsyncValue.data(data);
    }, error: (err, stackTrace) {
      state = AsyncValue.error(err, stackTrace: stackTrace);
    }, loading: () {
      state = const AsyncValue.loading();
    });
  }

  void addTodo(Todo todo) {
    if (state.hasValue) {
      final todoList = state.value ?? [];
      state = AsyncValue.data(List.from(todoList)..add(todo));
    }
  }
  ....
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM