Riverpod — podstata, kompilace závislostí ve Flutter

Autor: IT Sectr Publikováno: 2026-02-19 Doba čtení: 7 min

Riverpod — kompilovatelný správce stavu a závislostí pro Flutter, vytvořený Rémi Rousselem v roce 2021 jako nástupce Provider. Riverpod řeší zásadní problémy Provider: chybějící kontrolu při kompilaci, závislost na BuildContext a obtíže s ProviderNotFoundException. Podle údajů pub.dev balíček nasbíral přes 5 tisíc lajků a aktivně vytlačuje Provider v nových projektech.

Hlavní body

  • ProviderRef — objekt pro přístup k dalším providerům uvnitř provideru
  • AsyncValue — obal pro asynchronní data se stavy loading/error/data
  • Notifier — třída pro měnitelný stav s metodami změny
  • ProviderScope — kořenový widget spravující všechny providery
  • Code Generation — anotace @riverpod pro automatické generování providerů

Co je Riverpod?

Riverpod — knihovna pro správu stavu a vkládání závislostí ve Flutter, která kompiluje popis providerů do bezpečného Dart kódu. Na rozdíl od Provider nejsou providery Riverpod vázány na BuildContext: jsou vytvářeny globálně nebo v ProviderScope a jsou přístupné odkudkoli. Kompilátor kontroluje typy, závislosti a integritu grafu providerů ve fázi sestavení, čímž eliminuje runtime chyby jako ProviderNotFoundException.

Riverpod používá model override pro testování: každý provider může být přepsán pomocí ProviderScope.overrideWith bez nutnosti vytvářet podtřídy nebo mockovat rozhraní. To činí testování izolovaným: každý test dostane svou vlastní kopii grafu závislostí, která je plně kontrolována.

Podle Flutter Community Survey 2025 je Riverpod na třetím místě v popularitě po Provider a BLoC. Riverpod je zároveň nejrychleji rostoucím balíčkem: +120% instalací v roce 2024. Hlavní důvody: bezpečnost při kompilaci, absence ProviderNotFoundException, vestavěná podpora asynchronnosti přes AsyncValue.

Typy providerů

Riverpod poskytuje 8 typů providerů, každý pro konkrétní scénář: Provider (konstanta/služba), StateProvider (primitivní stav), StateNotifierProvider (složitá logika s StateNotifier), ChangeNotifierProvider (pro migraci z Provider), FutureProvider (asynchronní data, jednou), StreamProvider (reaktivní tok), NotifierProvider (nové API, Flutter 3.10+) a AsyncNotifierProvider (asynchronní Notifier).

Dart
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
  return CounterNotifier();
});

class CounterNotifier extends StateNotifier<int> {
  CounterNotifier() : super(0);

  void increment() => state++;
  void decrement() => state--;
}

class CounterScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);
    return Text('$count');
  }
}

ProviderRef — objekt předávaný každému provideru pro přístup k dalším providerům. ref.watch — přihlášení ke změnám, ref.read — jednorázové přečtení, ref.invalidate — resetování cache. ProviderRef nahrazuje BuildContext z Provider: jakýkoli provider může číst jiné providery bez přístupu ke stromu widgetů. To umožňuje vytvářet graf závislostí mimo vrstvu UI.

ProviderScope — povinný kořenový widget pro fungování Riverpod. ProviderScope ukládá všechny providery, spravuje jejich životní cyklus a ukládá hodnoty do cache. Bez ProviderScope aplikace spadne s ProviderNotFoundException. ProviderScope může být vnořený — vnořený scope přepisuje providery rodiče, což se používá pro testování a izolaci funkcí.

AsyncValue a práce s asynchronností

AsyncValue — sealed třída Riverpod pro reprezentaci asynchronního stavu. AsyncValue má tři varianty: AsyncData (úspěšná data), AsyncError (chyba), AsyncLoading (načítání). Místo ručního přepínání mezi loading/error/data každý FutureProvider nebo StreamProvider automaticky vrací AsyncValue a widget zpracovává všechny tři stavy přes ref.watch.

Dart
final userProvider = FutureProvider((ref) async {
  final api = ref.watch(apiProvider);
  return await api.fetchUser();
});

class UserScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final userAsync = ref.watch(userProvider);
    return userAsync.when(
      data: (user) => UserWidget(user),
      error: (e, _) => ErrorWidget(e.toString()),
      loading: () => CircularProgressIndicator(),
    );
  }
}

AsyncValue.when — metoda pro pattern matching všech tří stavů. Kompilátor kontroluje, že všechny tři případy jsou zpracovány — pokud se zapomene na loading nebo error, kód se nezkompiluje. AsyncValue.whenData — pouze pro data (pokud loading/error nejsou potřeba). AsyncValue.guard — try-catch obal pro převod výjimky na AsyncError. keepAlive — příznak, který zabraňuje zničení cache provideru při opuštění rozsahu viditelnosti.

Code Generation a @riverpod

Generování kódu — klíčová vlastnost Riverpod 2.0+. Anotace @riverpod nad funkcí automaticky generuje provider se správným typem, podporou refaktorování a automatickým doplňováním. Generování kódu používá riverpod_generator a build_runner. Vývojář napíše čistou funkci a vše ostatní — typy, třídy, factory konstruktory — se generuje automaticky.

Dart
@riverpod
String helloWorld(HelloWorldRef ref) {
  return 'Hello World';
}

// Vygenerováno: final helloWorldProvider = Provider((ref) => 'Hello World');

@riverpod
class Counter extends _$Counter {
  int build() => 0;
  void increment() => state++;
}

Notifier — nové API pro měnitelný stav s generováním kódu. Notifier je třída s metodou build() a metodami pro změnu stavu. Na rozdíl od StateNotifier, Notifier nevyžaduje samostatnou třídu stavu a poskytuje přímý přístup k state přes getter/setter. Riverpod automaticky generuje NotifierProvider pro každou třídu Notifier s anotací @riverpod.

build_runner: generování kódu se spouští příkazem dart run build_runner build. Generované soubory mají příponu .g.dart a importují se do zdrojového kódu. Při změně anotací nebo typů providerů je třeba generování kódu restartovat. Riverpod 2.x doporučuje generování kódu pro všechny nové projekty — ruční vytváření providerů zastarává.

Riverpod vs Provider

Hlavní rozdíly Riverpod oproti Provider: nezávislost na BuildContext, bezpečnost při kompilaci, vestavěná práce s asynchronností, automatické cache a testování přes override. Provider vyžaduje BuildContext pro přístup ke stavu (context.watch, context.read), Riverpod používá WidgetRef a globálně deklarované providery.

VlastnostProviderRiverpod
Závislost na BuildContextAnoNe
Kontrola při kompilaciNeAno (přes @riverpod)
ProviderNotFoundExceptionRuntimeNemožný
AsynchronnostRučníAsyncValue (vestavěný)
TestováníObal v ProviderProviderScope.overrideWith
CacheNeAutomatické + keepAlive

Migrace z Provider: Riverpod podporuje ChangeNotifierProvider.adaptive pro použití stávajících ChangeNotifier bez přepisování. Postupná migrace: nejprve se nové funkce píší v Riverpod, poté se staré Provider nahrazují providery Riverpod přes adaptér. Oba balíčky mohou koexistovat v jednom projektu, což umožňuje migraci bez zmrazení vývoje.

Testování Riverpod

Testování Riverpod je postaveno na ProviderScope.overrideWith. Každý provider je přepsán uvnitř testovacího ProviderScope bez mocků a DI kontejnerů. ProviderContainer — izolované prostředí pro testy bez Flutter (čistý Dart), umožňující testování providerů bez vykreslování widgetů.

Dart
import 'package:flutter_test/flutter_test.dart';
import 'package:riverpod/riverpod.dart';

void main() {
  test('Counter increments correctly', () {
    final container = ProviderContainer();
    container.read(counterProvider.notifier).increment();
    expect(container.read(counterProvider), 1);
  });

  testWidgets('UI updates on increment', (tester) async {
    await tester.pumpWidget(
      ProviderScope(
        overrides: [counterProvider.overrideWithValue(5)],
        child: CounterScreen(),
      ),
    );
    expect(find.text('5'), findsOneWidget);
  });
}

ProviderContainer — bez Flutter. Použijte ProviderContainer pro unit testy providerů bez widgetů. overrideWithValue — nahrazení provideru konkrétní hodnotou. overrideWith — nahrazení továrnou provideru (pro mockování služeb). autodispose — v testech zkontrolujte, zda je provider zničen při opuštění rozsahu viditelnosti pomocí container.dispose().

Často kladené otázky

Čím se Riverpod liší od BLoC?

Riverpod — knihovna pro správu stavu s globálními providery, AsyncValue a generováním kódu. BLoC — architektonický vzor s Event → Stream → State. Riverpod se snadněji učí a má lepší DX díky @riverpod anotacím. BLoC poskytuje přísnou izolaci business logiky a sledování Event přes BlocObserver. Volba závisí na paradigmatu projektu: Riverpod je blíže Provider, BLoC — reaktivním tokům.

Co je autodispose v Riverpod?

Autodispose — mechanismus automatického zničení provideru, když na něj nikdo není přihlášen. Ve výchozím nastavení jsou všechny Riverpod providery autodispose: při opuštění widgetu ze stromu je provider odstraněn z paměti. keepAlive — příznak, který vypíná autodispose pro providery, které mají žít vždy (API klienti, repozitáře, nastavení). To zabraňuje únikům paměti — nepoužívané providery jsou automaticky ničeny.

Jak funguje ref.invalidate?

ref.invalidate — metoda, která vynuceně resetuje cache provideru. Po invalidate je provider znovu vytvořen při příštím čtení: FutureProvider znovu provede async funkci, StreamProvider se znovu přihlásí k toku. Použijte invalidate pro vynucené obnovení dat (pull-to-refresh, změna uživatele). ref.refresh — kombinace invalidate + čtení: resetuje a okamžitě přečte novou hodnotu v jedné operaci.

Lze Riverpod použít bez generování kódu?

Ano. Riverpod 1.x funguje pouze bez generování kódu — providery se vytvářejí ručně přes Provider(), StateNotifierProvider(), FutureProvider() atd. Riverpod 2.x podporuje oba přístupy. Bez generování kódu je více boilerplate, ale není závislost na build_runner a dart run build_runner build. Pro malé projekty (do 30 providerů) je ruční vytváření ospravedlnitelné, pro velké projekty je generování kódu povinné.

Co jsou Family providery?

Family — modifikátor provideru, který přijímá externí parametr. Například userProvider(123) — provider načítající uživatele s ID 123. Family providery ukládají výsledek pro každý jedinečný parametr zvlášť. Použijte Family pro seznam prvků, kde se každý prvek načítá podle ID. Modifikátor Family je k dispozici pro všechny typy providerů: Provider.family, FutureProvider.family, StreamProvider.family.

Shrnutí

  • Riverpod — kompilovatelný správce stavu, nástupce Provider bez ProviderNotFoundException
  • ProviderRef — náhrada za BuildContext pro přístup k providerům uvnitř jiných providerů
  • AsyncValue — sealed třída se stavy loading/error/data pro asynchronní data
  • Generování kódu @riverpod — automatické odvození typů a továren providerů
  • ProviderScope.overrideWith — izolované testování bez mocků a DI kontejnerů
  • Family — parametrizované providery s individuálním cache
  • autodispose a keepAlive — automatická správa životního cyklu providerů

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také