I'm getting this compiler error in the following provider code:
The argument type 'AsyncCatNotifier Function(dynamic)' can't be assigned to the parameter type 'AsyncCatNotifier Function()'.dartargument_type_not_assignable (new) AsyncCatNotifier AsyncCatNotifier({required NetworkService networkService}) package:coolcatsclient/providers/provider_async_cat.dart
class AsyncCatNotifier extends AsyncNotifier<AsyncValue<Cat?>> {
final NetworkService networkService;
AsyncCatNotifier({required this.networkService}) : super();
Future<void> fetchCat(int catId) async {
try {
final cat = await networkService.fetchCat(catId);
state = AsyncData(AsyncData(cat)); // Update state with fetched cat
} catch (error, stackTrace) {
state = AsyncError(error, stackTrace); // Handle errors
}
}
@override
FutureOr<AsyncValue<Cat?>> build() {
return const AsyncLoading(); // Default initial state while loading
}
}
final asyncCatProvider = AsyncNotifierProvider.autoDispose<AsyncCatNotifier, AsyncValue<Cat?>>(
// compiler error happens here
(ref) => AsyncCatNotifier(networkService: ref.read(networkServiceProvider)),
);
There are a few things to keep in mind when using AsyncNotifier
.
build
method. Either by using Ref.watch
or from the build
parameters (family).AsyncNotifier
to be auto disposed, extends AutoDisposeAsyncNotifier
, there are also FamilyAsyncNotifier
and AutoDisposeFamilyAsyncNotifier
. Consider using code generation to avoid dealing with the type of Notifier
/Provider
.AsyncNotifier
's type argument with AsyncValue
. The state of an AsyncNotifier
is AsyncValue<T>
where T
is the type argument of the AsyncNotifier
.
For instance, your AsyncCatNotifier
should probably extends AutoDisposeAsyncNotifier<Cat?>
.AsyncLoading()
inside the AsyncNotifier
's build
method is undesirable most of the time. Instead, initialise the AsyncNotifier
right a way.AsyncNotifier
, consider converting it to a FutureProvider
.Below is how I would implement it:
// A simple provider for other providers to access NetworkService.
final networkServiceProvider = Provider<NetworkService>((ref) {
return NetworkService();
});
// A simple future auto dispose family provider to fetch a Cat.
final catProvider = AutoDisposeFutureProviderFamily<Cat, int>((ref, catId) async {
final networkService = ref.watch(networkServiceProvider);
final cat = await networkService.fetchCat(catId);
return cat;
});
// To consume the catProvider.
final cat = ref.watch(catProvider(1));
return cat.when(
data: (cat) => Text('Cat id: ${cat.id}'),
loading: () => const CircularProgressIndicator(),
error: (error, stackTrace) => Text('Error: $error'),
),
Below is a Dog
version with code generation. Notice how it let you
Notifier
/Provider
's type, you do not have to choose between AsyncNotifier
/AutoDisposeAsyncNotifier
/FamilyAsyncNotifier
/AutoDisposeFamilyAsyncNotifier
@riverpod
NetworkService networkService(NetworkServiceRef ref) {
return NetworkService();
}
@riverpod
FutureOr<Dog> dog(
DogRef ref, {
required int dogId,
}) async {
final networkService = ref.watch(networkServiceProvider);
final dog = await networkService.fetchDog(dogId);
return dog;
}
final dog = ref.watch(dogProvider(dogId: 1));