I have a StateNotifierProvider
that depends on a FutureProvider
. Currently they look like below.
final catalogProvider = StateNotifierProvider<CatalogNotifier, CatalogState>((ref) {
final network = ref.watch(networkProvider.future); // future provider
return CatalogNotifier(network: network);
});
this makes my CatalogNotifier
accept a Future<NetworkProvider>
instead of NetworkProvider
and requires me to do things like below.
await (await network).doGet(...)
What's the best way to avoid having to await multiple and allow CatalogNotifier
to accept a bare NetworkProvider
so I can write like await network.doGet(...)
?
for completeness as requested, below is the other related providers
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,
));
I'm sure I can take my cache provider as a future into the network provider, so it doesn't have to be a FutureProvider
, but I'm interested in how to solve the issue above, since in another scenario, if I depend on say 3 or 4 FutureProvider
s, this may not be an option.
With Riverpod v2 and its code-gen features this has become much easier since you no longer have to decide the type of the provider (unless you want to).
@riverpod
Future<CatalogController> catalog(CatalogRef ref) async {
final network = await ref.watch(networkProvider.future);
return CatalogController(network: network);
}
Quite often you want to have a value calculated and have a way to explicitly redo that calculation from the UI, like a list from network, but with a refresh button in the UI. This can be modeled as below in 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 also has loading and error properties for the providers. You can use these to show the UI accordingly. Though if you want to show the last result from the provider while your feed is loading or in an error state, you have to model this yourself with a provider that returns a stream/BehaviorSubject, caches the last value, etc.