-
IntroA lot of my controllerProviders (AsyncNotfiers) which perform data mutations follow the same patterns and it's getting pretty repetitive. I was looking for a way to introduce inheritance to solve the issue. ProblemThe problem is that I cannot seem to find a way to extend AsyncNotifiers (with a provider still being created for the subclass) when code gen is being used. Example of desired outcomeParent AsyncNotifier: @riverpod
class ParentAsyncNotifier extends _$ParentAsyncNotifier {
@override
FutureOr<void> build() async {
return null;
}
Future<void> mutation() async {
...
}
} Child AsyncNotifier: class ChildAsyncNotifier extends ParentAsyncNotifier {
void someAction() {
codeBlock1();
super.mutate();
codeBlock2();
}
} in myy Widgets: ref.watch(childNotifierProvider); |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
That is not supported. You can use mixins instead |
Beta Was this translation helpful? Give feedback.
-
For anyone curios, here's my solution: (Note thanks to @rrousselGit for the advice) /// Provides basic structure for Riverpod
/// mutation controllers
///
/// Call `performMutationAction` to perform a mutation action.
///
/// Call `onBuild` inside `build`.
///
/// Assuming your controllers use AutoDispose (still no idea how to make it work with both options)
mixin MutationControllerMixin on AutoDisposeAsyncNotifier {
/// Executed during [build]
Future<void> onBuild() async {
disposedStatusMount(ref);
}
/// Performs a mutation action
///
/// Handles success and error messages,
/// state updates, etc.
///
/// Sets state to value returned by [mutationAction].
/// Sets state to `AsyncLoading` in meantime.
Future<void> performMutationAction({
/// The action to be performed
required Future<T> Function<T>() mutationAction,
}) async {
final localizations = ref.read(appLocalizationsProvider);
state = const AsyncLoading();
final result = await AsyncValue.guard(() async {
await mutationAction();
});
if (!isDisposed) {
state = result;
}
if (!state.hasError) {
// Handle success
}
if (state.hasError) {
// Handle error
}
}
/// Must be called inside [build].
void disposedStatusMount(Ref ref) {
disposedStatusKey = Object();
ref.onDispose(() => disposedStatusKey = null);
}
/// Whether or not the [AsyncNotifier] has been disposed
bool get isDisposed => disposedStatusKey == null;
} |
Beta Was this translation helpful? Give feedback.
For anyone curios, here's my solution: (Note thanks to @rrousselGit for the advice)