- For apps already on Riverpod using ChangeNotifierProvider, this guide moves to AsyncNotifier (and Notifier where state is sync).
Why migrate#
- ChangeNotifier leads to isLoading / hasError flags and lots of try/catch/finally and notifyListeners().
- AsyncNotifier uses a single state and AsyncValue; Riverpod handles loading/error; less boilerplate and fewer inconsistent states.
Steps#
-
Choose the notifier type
- Side effects (methods that change state)? โ Class-based (Notifier or AsyncNotifier).
- Async load (e.g. network)? โ AsyncNotifier
. - Parameters? โ Add them to the notifier (e.g. constructor + field) and use family/provider that passes them.
-
Declaration
- Replace ChangeNotifierProvider with AsyncNotifierProvider (or NotifierProvider if sync).
- State type: e.g. AsyncNotifier<List
> ; no separate todos / isLoading / hasErrorโjust state and AsyncValue.
-
Initialization
- Move init from a custom method (e.g. init) into build.
- build returns Future<List
> ; Riverpod exposes AsyncValue<List> to the UI. No manual try/catch in build.
-
Mutations
- Replace flag updates and notifyListeners with state = newValue (and state = AsyncValue.data(...) or AsyncValue.error(...) if you construct explicitly). Use ref for dependencies (ref.watch, ref.read) inside methods.
-
Consumers
- ref.watch(provider) now gets AsyncValue
; handle loading/error/data in the UI. Use ref.read(provider.notifier) to call methods.
- ref.watch(provider) now gets AsyncValue
Summary#
- Init in build; no todos/isLoading/hasError.
- No try-catch-finally in build; return the Future.
- Side effects: reassign state; use ref for other providers.
- See riverpod-providers and riverpod-refs for Notifier/AsyncNotifier and Ref APIs.