AsyncNotifier- en FutureProvider-gegevenspijplijnen
Modelleer laad-, fout- en gegevensstatussen overzichtelijk met patronen voor AsyncNotifier en AsyncValue.
AsyncNotifier- en FutureProvider-gegevenspijplijnen is een gratis Mobiele ontwikkeling met Flutter-les op CoddyKit. Dit is les 3 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Mobiele ontwikkeling met Flutter. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Mobiele ontwikkeling met Flutter bevat in totaal 4 lessen.
De drie statussen van asynchrone gegevens
Elk scherm dat gegevens van het netwerk laadt, moet drie vragen beantwoorden: Worden de gegevens geladen? Is er een fout opgetreden? Wat zijn de gegevens?
Riverpod 2.0 modelleert deze drie statussen met één sealed type, genaamd AsyncValue<T>. In plaats van afzonderlijke velden voor isLoading, error en data handmatig te beheren, ontvang je één waarde die altijd precies één van drie vormen heeft:
AsyncLoading<T>— de future wordt nog uitgevoerdAsyncError<T>— de uitvoering is mislukt en bevat de fout en stacktraceAsyncData<T>— de uitvoering is geslaagd en bevat de waarde
Zowel FutureProvider als AsyncNotifier stellen hun state beschikbaar als een AsyncValue. Daarom ziet de UI-code voor beide er hetzelfde uit.
FutureProvider: de eenvoudigste pijplijn
FutureProvider is de lichtste manier om een asynchrone berekening uit te voeren en het resultaat beschikbaar te maken. Je geeft een asynchrone callback op; Riverpod voert die uit, slaat het resultaat in de cache op en bouwt afhankelijke onderdelen opnieuw op wanneer de state van laden naar gegevens of een fout gaat.
Gebruik dit wanneer de gegevens alleen-lezen zijn en geen methoden met bijwerkingen hebben — bijvoorbeeld wanneer je één keer een gebruikersprofiel ophaalt en weergeeft.
final userProfileProvider = FutureProvider<UserProfile>((ref) async {
final repo = ref.watch(profileRepositoryProvider);
return repo.fetchProfile();
});
// In a ConsumerWidget
Widget build(BuildContext context, WidgetRef ref) {
final profile = ref.watch(userProfileProvider);
return profile.when(
loading: () => const CircularProgressIndicator(),
error: (err, st) => Text('Failed: $err'),
data: (p) => Text('Hello, ${p.name}'),
);
}Patroonvergelijking met .when
De methode .when verplicht je om alle drie de gevallen af te handelen, zodat je nooit een laadindicator of foutmelding vergeet. Dit is de gebruikelijke manier om een AsyncValue in de UI weer te geven.
Er zijn twee extra opties die je moet kennen:
skipLoadingOnRefresh— blijf oude gegevens tonen terwijl op de achtergrond wordt vernieuwd, in plaats van kort een laadindicator te tonen.skipLoadingOnReload— hetzelfde wanneer een afhankelijkheid de provider opnieuw opbouwt.
Voor meer controle kun je ook rechtstreeks patroonvergelijking toepassen op de sealed subklassen met switch-expressies van Dart 3.
final state = ref.watch(userProfileProvider);
final widget = switch (state) {
AsyncData(:final value) => Text('Hello, ${value.name}'),
AsyncError(:final error) => Text('Error: $error'),
_ => const CircularProgressIndicator(),
};Wanneer je methoden nodig hebt: AsyncNotifier
FutureProvider kan alleen lezen. Zodra je de state moet wijzigen — vernieuwen, toevoegen, omschakelen of verwijderen — gebruik je AsyncNotifier.
Een AsyncNotifier<T> heeft een build()-methode die een Future<T> retourneert voor het eerste laden, plus je eigen openbare methoden die state bijwerken. De klasse bevat de bedrijfslogica; de widget roept alleen de methoden aan.
Belangrijke regel: build() is de initiële pijplijn. Riverpod verpakt het resultaat automatisch, zodat state begint als AsyncLoading en daarna AsyncData of AsyncError wordt — voor het eerste laden hoef je deze waarden nooit handmatig in te stellen.
class TodosNotifier extends AsyncNotifier<List<Todo>> {
@override
Future<List<Todo>> build() async {
final repo = ref.watch(todoRepositoryProvider);
return repo.fetchTodos();
}
}
final todosProvider =
AsyncNotifierProvider<TodosNotifier, List<Todo>>(TodosNotifier.new);Wijzigen met AsyncValue.guard
Binnen een mutatiemethode moet je vóór het asynchrone werk state = const AsyncLoading() instellen en daarna gegevens of een fout opvangen. Zo'n try/catch handmatig schrijven is repetitief en gemakkelijk verkeerd te doen.
AsyncValue.guard doet dit voor je: het voert een asynchrone callback uit en retourneert bij succes AsyncData of bij een fout AsyncError (met de stacktrace). Zo blijven de laad- en foutstatussen automatisch consistent.
Future<void> addTodo(String label) async {
final repo = ref.read(todoRepositoryProvider);
// Show a spinner while the write happens.
state = const AsyncValue.loading();
state = await AsyncValue.guard(() async {
await repo.create(label);
return repo.fetchTodos(); // fresh list becomes the new state
});
}Optimistische updates met de huidige waarde
Elke tik beantwoorden met een schermvullende laadindicator voelt haperend aan. Een betere mobiele gebruikerservaring laat de bestaande lijst staan en vervangt die pas door de nieuwe gegevens wanneer die binnen zijn.
De truc is om state.value (de laatst bekende gegevens) te lezen en deze via copyWithPrevious door te geven aan AsyncLoading, of gewoon de volgende lijst optimistisch op te bouwen. Riverpods requireValue geeft je de gegevens terug of gooit een fout als ze er nog niet zijn.
Future<void> toggle(String id) async {
final previous = state.requireValue;
// Optimistic: update UI immediately.
final optimistic = [
for (final t in previous)
if (t.id == id) t.copyWith(done: !t.done) else t,
];
state = AsyncData(optimistic);
// Reconcile with the server; revert on failure.
state = await AsyncValue.guard(() async {
await ref.read(todoRepositoryProvider).toggle(id);
return ref.read(todoRepositoryProvider).fetchTodos();
});
}Vernieuwen en ongeldig maken
Als je de pijplijn van een provider opnieuw wilt uitvoeren vanuit de gebruikersinterface — bijvoorbeeld bij omlaag trekken om te vernieuwen — roep je geen methode op de notifier aan. Je vraagt Riverpod om de provider opnieuw op te bouwen:
ref.invalidate(provider)— verwijdert de waarde uit de cache;build()wordt bij de volgende lezing opnieuw uitgevoerd.ref.refresh(provider)— doet hetzelfde, maar geeft de nieuwe waarde of future terug, zodat je erop kuntawaiten.
Omdat build() opnieuw wordt uitgevoerd, doorloopt de toestand automatisch opnieuw AsyncLoading en daarna AsyncData. Combineer dit met skipLoadingOnRefresh: false als je wel een laadindicator tijdens het vernieuwen wilt tonen.
RefreshIndicator(
onRefresh: () => ref.refresh(todosProvider.future),
child: ref.watch(todosProvider).when(
loading: () => const Center(child: CircularProgressIndicator()),
error: (e, st) => ErrorView(error: e),
data: (todos) => TodoListView(todos: todos),
),
);Providers koppelen in een pijplijn
Stromen met echte gegevens zijn pijplijnen: een authenticatietoken levert een gebruikers-id, die vervolgens een bestellijst oplevert. Met Riverpod druk je dit uit door binnen de ene asynchrone provider een andere met watch te observeren.
Wanneer je await ref.watch(other.future) gebruikt, wacht de buitenste provider op de gegevens van de binnenste provider. Als de binnenste provider opnieuw gegevens uitstuurt, wordt de buitenste pijplijn automatisch opnieuw uitgevoerd. Zo combineer je AsyncValues zonder handmatig koppelen.
final ordersProvider = FutureProvider<List<Order>>((ref) async {
// Wait for the upstream user before fetching their orders.
final user = await ref.watch(userProfileProvider.future);
final repo = ref.watch(orderRepositoryProvider);
return repo.fetchOrdersFor(user.id);
});Pijplijnen met parameters met .family
Vaak hangt de pijplijn af van een argument — een product-id of een zoekopdracht. De modifier .family maakt voor elk argument een afzonderlijke providerinstantie, elk met een eigen gecachte AsyncValue.
Combineer dit met autoDispose, zodat instanties worden vrijgegeven wanneer geen enkele widget ze meer observeert — belangrijk op mobiele apparaten om geheugenlekken tijdens het navigeren te voorkomen.
final productProvider = FutureProvider.autoDispose
.family<Product, String>((ref, id) async {
final repo = ref.watch(catalogRepositoryProvider);
return repo.fetchProduct(id);
});
// Usage: each id gets its own loading/error/data cache.
final product = ref.watch(productProvider('sku-42'));AsyncValue modelleren zonder Flutter
Om het model met drie toestanden echt te begrijpen, helpt het om het als gewone Dart te bekijken. Hieronder staat een kleine implementatie met sealed classes die het gedrag van AsyncValue nabootst — laden, fout en gegevens — met daaroverheen een vouwbewerking in de stijl van when.
Dit is precies het mentale model dat Riverpod intern gebruikt; het echte type voegt alleen caching, het bijhouden van vorige waarden en stacktraces toe.
sealed class Async<T> {
const Async();
}
class Loading<T> extends Async<T> { const Loading(); }
class Failure<T> extends Async<T> {
final Object error;
const Failure(this.error);
}
class Data<T> extends Async<T> {
final T value;
const Data(this.value);
}
String render(Async<int> s) => switch (s) {
Loading() => 'loading...',
Failure(:final error) => 'error: $error',
Data(:final value) => 'data: $value',
};
void main() {
print(render(const Loading()));
print(render(const Failure('timeout')));
print(render(const Data(42)));
}Veelvoorkomende valkuilen in pijplijnen vermijden
Met een paar regels houd je de pijplijnen van je AsyncNotifier schoon:
- Gebruik binnen
build()nooitref.readvoor afhankelijkheden — gebruikref.watch, zodat de pijplijn opnieuw wordt opgebouwd wanneer ze veranderen. Gebruikref.readalleen binnen mutatiemethoden die één keer worden uitgevoerd. - Vang fouten in
build()niet op om ze vervolgens te negeren — laat ze worden gegooid, zodat de toestandAsyncErrorwordt en de gebruikersinterface de fout kan tonen. - Geef de future terug, niet void vanuit vernieuwingshandlers, zodat omlaag trekken om te vernieuwen op voltooiing kan wachten.
- Houd
build()idempotent — het kan vaak worden uitgevoerd; vermijd bijwerkingen daar.
Korte controle: lezen tegenover wijzigen
Je bouwt een scherm voor taken. De lijst wordt geladen vanuit een API en gebruikers kunnen nieuwe taken toevoegen. Welke providerkeuze is correct?
Samenvatting
Je beschikt nu over de volledige gereedschapskist voor asynchrone gegevenspijplijnen in Riverpod 2.0:
AsyncValue<T>modelleert laden / fout / gegevens als één sealed waarde, die je weergeeft met.whenof eenswitch.FutureProvideris bedoeld voor alleen-lezen van asynchrone gegevens, zonder methoden.AsyncNotifiervoegt mutatiemethoden toe;build()is de eerste pijplijn en moet voor afhankelijkhedenref.watchgebruiken.AsyncValue.guardverpakt mutaties, zodat laad- en fouttoestanden consistent blijven;requireValuemaakt optimistische updates mogelijk.ref.invalidate/ref.refreshvoeren de pijplijn opnieuw uit;.familyenautoDisposeregelen pijplijnen met parameters die veilig met geheugen omgaan.
Gebruik FutureProvider wanneer je alleen leest, en AsyncNotifier zodra je iets moet schrijven.
Leer Dart met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 22
- Lessen
- 88
Veelgestelde vragen
Is de les “AsyncNotifier- en FutureProvider-gegevenspijplijnen” gratis?
Ja — je kunt hier op het web alle 3 lessen van het leerpad Mobiele ontwikkeling met Flutter, waaronder “AsyncNotifier- en FutureProvider-gegevenspijplijnen”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Mobiele ontwikkeling met Flutter bevat in totaal 4 lessen.
Wat leer ik in “AsyncNotifier- en FutureProvider-gegevenspijplijnen”?
Modelleer laad-, fout- en gegevensstatussen overzichtelijk met patronen voor AsyncNotifier en AsyncValue. Je oefent met Mobiele ontwikkeling met Flutter door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Mobiele ontwikkeling met Flutter te beginnen?
Ervaring vooraf is niet nodig. Mobiele ontwikkeling met Flutter op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.
Hoe lang duurt de les “AsyncNotifier- en FutureProvider-gegevenspijplijnen”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Mobiele ontwikkeling met Flutter?
Ja. Elke les over Mobiele ontwikkeling met Flutter bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Van Provider naar Riverpod: legacy-state migreren
- Codegeneratie met riverpod_generator en @riverpod
- AsyncNotifier- en FutureProvider-gegevenspijplijnen
- Providers scopen, overschrijven en ProviderObserver