Riverpod — lényeg, függőségek fordításának összeállítása Flutter-ben

Szerző: IT Sectr Megjelenés: 2026-02-19 Olvasási idő: 7 perc

Riverpod — egy fordítási időben összeállítható állapot- és függőségkezelő Flutter-hez, amelyet Rémi Roussel hozott létre 2021-ben a Provider utódjaként. A Riverpod megoldja a Provider alapvető problémáit: a fordítási ellenőrzés hiányát, a BuildContext-től való függőséget és a ProviderNotFoundException nehézségeit. A pub.dev adatai szerint a csomag több mint 5 ezer lájkot gyűjtött, és aktívan kiszorítja a Provider-t az új projektekben.

Főbb pontok

  • ProviderRef — objektum más provider-ek eléréséhez egy provider-en belül
  • AsyncValue — becsomagoló aszinkron adatokhoz loading/error/data állapotokkal
  • Notifier — osztály mutable állapothoz változtatási metódusokkal
  • ProviderScope — gyökér widget, amely az összes provider-t kezeli
  • Code Generation — @riverpod annotációk a provider-ek automatikus generálásához

Mi az a Riverpod?

Riverpod — egy könyvtár állapotkezeléshez és függőséginjektáláshoz Flutter-ben, amely a provider-ek leírását biztonságos Dart kódba fordítja. A Provider-rel ellentétben a Riverpod provider-ek nem kötődnek a BuildContext-hez: globálisan vagy ProviderScope-ban jönnek létre, és bárhonnan elérhetők. A fordító ellenőrzi a típusokat, függőségeket és a provider-gráf integritását az építési fázisban, kiküszöbölve a runtime hibákat, mint a ProviderNotFoundException.

A Riverpod az override modellt használja a teszteléshez: minden provider felülírható a ProviderScope.overrideWith segítségével anélkül, hogy alosztályokat kellene létrehozni vagy interfészeket mock-olni. Ez izoláltá teszi a tesztelést: minden teszt megkapja a függőségi gráf saját másolatát, amely teljes mértékben kontrollált.

A Flutter Community Survey 2025 szerint a Riverpod a harmadik helyen áll népszerűségben a Provider és a BLoC után. Ugyanakkor a Riverpod a leggyorsabban növekvő csomag: +120% telepítés 2024-ben. Fő okok: fordítási biztonság, a ProviderNotFoundException hiánya, beépített aszinkron támogatás az AsyncValue-on keresztül.

Provider típusok

A Riverpod 8 típusú provider-t kínál, mindegyiket egy adott forgatókönyvhöz: Provider (konstans/szolgáltatás), StateProvider (primitív állapot), StateNotifierProvider (komplex logika StateNotifier-rel), ChangeNotifierProvider (Provider-ről való migráláshoz), FutureProvider (aszinkron adatok, egyszer), StreamProvider (reaktív adatfolyam), NotifierProvider (új API, Flutter 3.10+) és AsyncNotifierProvider (aszinkron 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 — az objektum, amelyet minden provider-nek átadnak más provider-ek eléréséhez. ref.watch — feliratkozás változásokra, ref.read — egyszeri olvasás, ref.invalidate — a gyorsítótár visszaállítása. A ProviderRef helyettesíti a BuildContext-et a Provider-ből: bármely provider olvashat más provider-eket anélkül, hogy hozzáférne a widget-fához. Ez lehetővé teszi a függőségi gráf felépítését az UI rétegen kívül.

ProviderScope — a Riverpod működéséhez kötelező gyökér widget. A ProviderScope tárolja az összes provider-t, kezeli azok életciklusát és gyorsítótárazza az értékeket. ProviderScope nélkül az alkalmazás ProviderNotFoundException hibával összeomlik. A ProviderScope lehet egymásba ágyazott — a beágyazott scope felülírja a szülő provider-eit, amit teszteléshez és funkciók izolálásához használnak.

AsyncValue és munka aszinkronitással

AsyncValue — a Riverpod sealed osztálya az aszinkron állapot reprezentálására. Az AsyncValue-nak három változata van: AsyncData (sikeres adatok), AsyncError (hiba), AsyncLoading (betöltés). A loading/error/data közötti manuális váltogatás helyett minden FutureProvider vagy StreamProvider automatikusan AsyncValue-t ad vissza, és a widget mindhárom állapotot kezeli a ref.watch segítségével.

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 — metódus mindhárom állapot mintájának illesztésére. A fordító ellenőrzi, hogy mindhárom eset kezelve van-e — ha a loading vagy error kimarad, a kód nem fog lefordulni. AsyncValue.whenData — csak data esetén (ha loading/error nem szükséges). AsyncValue.guard — try-catch becsomagoló a kivételek AsyncError-ré alakításához. keepAlive — egy jelző, amely megakadályozza a provider gyorsítótárának megsemmisítését a láthatósági tartomány elhagyásakor.

Code Generation és @riverpod

Kódgenerálás — a Riverpod 2.0+ kulcsfontosságú jellemzője. A @riverpod annotáció egy függvény felett automatikusan létrehoz egy provider-t a megfelelő típussal, refaktorálási támogatással és automatikus kiegészítéssel. A kódgenerálás a riverpod_generator és build_runner eszközöket használja. A fejlesztő tiszta függvényt ír, és minden mást — típusokat, osztályokat, factory konstruktorokat — automatikusan generál a rendszer.

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

// Generálva: final helloWorldProvider = Provider((ref) => 'Hello World');

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

Notifier — új API mutable állapothoz kódgenerálással. A Notifier egy osztály build() metódussal és állapotváltoztató metódusokkal. A StateNotifier-rel ellentétben a Notifier nem igényel külön állapot osztályt, és közvetlen hozzáférést biztosít a state-hez getter/setter segítségével. A Riverpod automatikusan létrehoz NotifierProvider-t minden @riverpod annotációval rendelkező Notifier osztályhoz.

build_runner: a kódgenerálás a dart run build_runner build paranccsal indítható el. A generált fájlok .g.dart utótaggal rendelkeznek, és importálásra kerülnek a forráskódba. Az annotációk vagy provider típusok változásakor a kódgenerálást újra kell futtatni. A Riverpod 2.x a kódgenerálást ajánlja minden új projekthez — a provider-ek manuális létrehozása elavul.

Riverpod vs Provider

Fő különbségek a Riverpod és a Provider között: függetlenség a BuildContext-től, fordítási biztonság, beépített aszinkron munka, automatikus gyorsítótárazás és tesztelés override segítségével. A Provider BuildContext-et igényel az állapot eléréséhez (context.watch, context.read), a Riverpod WidgetRef-et és globálisan deklarált provider-eket használ.

JellemzőProviderRiverpod
Függőség BuildContext-tőlIgenNem
Fordítási ellenőrzésNemIgen (@riverpod segítségével)
ProviderNotFoundExceptionRuntimeLehetetlen
AszinkronitásManuálisAsyncValue (beépített)
TesztelésBecsomagolás Provider-beProviderScope.overrideWith
GyorsítótárazásNemAutomatikus + keepAlive

Migráció Provider-ről: A Riverpod támogatja a ChangeNotifierProvider.adaptive használatát a meglévő ChangeNotifier-ek átírás nélküli használatához. Lépésenkénti migráció: először az új funkciókat Riverpod-del írják, majd a régi Provider-eket Riverpod provider-ekre cserélik adapteren keresztül. Mindkét csomag együtt létezhet egy projektben, lehetővé téve a migrációt a fejlesztés leállítása nélkül.

Riverpod tesztelése

A Riverpod tesztelése a ProviderScope.overrideWith-ra épül. Minden provider felülíródik a teszt ProviderScope-on belül mock-ok és DI konténerek nélkül. ProviderContainer — izolált környezet Flutter nélküli (tiszta Dart) tesztekhez, lehetővé téve a provider-ek tesztelését widget-ek megjelenítése nélkül.

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 — Flutter nélkül. Használja a ProviderContainer-t a provider-ek egységteszteléséhez widget-ek nélkül. overrideWithValue — a provider helyettesítése egy adott értékkel. overrideWith — helyettesítés provider gyárral (szolgáltatások mock-olásához). autodispose — tesztekben ellenőrizze, hogy a provider megsemmisül-e a láthatósági tartomány elhagyásakor a container.dispose() segítségével.

Gyakran Ismételt Kérdések

Miben különbözik a Riverpod a BLoC-tól?

Riverpod — állapotkezelő könyvtár globális provider-ekkel, AsyncValue-val és kódgenerálással. BLoC — architektúra minta Event → Stream → State felépítéssel. A Riverpod könnyebben megtanulható és jobb fejlesztői élményt nyújt a @riverpod annotációkon keresztül. A BLoC szigorú üzleti logikai elkülönítést és Event-követést biztosít a BlocObserver segítségével. A választás a projekt paradigmájától függ: a Riverpod közelebb áll a Provider-hez, a BLoC a reaktív adatfolyamokhoz.

Mi az autodispose a Riverpod-ban?

Autodispose — a provider automatikus megsemmisítésének mechanizmusa, amikor senki sincs rá feliratkozva. Alapértelmezetten minden Riverpod provider autodispose: amikor a widget elhagyja a fát, a provider törlődik a memóriából. keepAlive — egy jelző, amely kikapcsolja az autodispose-t azon provider-eknél, amelyeknek mindig élniük kell (API kliensek, repository-k, beállítások). Ez megakadályozza a memóriaszivárgást — a nem használt provider-ek automatikusan megsemmisülnek.

Hogyan működik a ref.invalidate?

ref.invalidate — egy metódus, amely kényszeríti a provider gyorsítótárának visszaállítását. Az invalidate után a provider a következő olvasáskor újra létrejön: a FutureProvider újra végrehajtja az async függvényt, a StreamProvider újra feliratkozik az adatfolyamra. Használja az invalidate-t az adatok kényszerített frissítéséhez (pull-to-refresh, felhasználóváltás). ref.refresh — az invalidate + olvasás kombinációja: visszaállítja és azonnal beolvassa az új értéket egyetlen műveletben.

Használható a Riverpod kódgenerálás nélkül?

Igen. A Riverpod 1.x csak kódgenerálás nélkül működik — a provider-ek manuálisan jönnek létre a Provider(), StateNotifierProvider(), FutureProvider() stb. segítségével. A Riverpod 2.x mindkét megközelítést támogatja. Kódgenerálás nélkül több boilerplate van, de nincs függőség a build_runner-től és a dart run build_runner build-től. Kis projekteknél (30 provider-ig) a manuális létrehozás indokolt, nagy projekteknél a kódgenerálás kötelező.

Mik azok a Family provider-ek?

Family — egy provider módosító, amely külső paramétert fogad el. Például userProvider(123) — egy provider, amely betölti a 123-as ID-jű felhasználót. A Family provider-ek minden egyedi paraméterhez külön gyorsítótárazzák az eredményt. Használja a Family-t olyan elemek listájához, ahol minden elem ID alapján töltődik be. A Family módosító minden provider típushoz elérhető: Provider.family, FutureProvider.family, StreamProvider.family.

Összefoglaló

  • Riverpod — fordítási időben összeállítható állapotkezelő, a Provider utódja ProviderNotFoundException nélkül
  • ProviderRef — a BuildContext helyettesítője provider-ek eléréséhez más provider-eken belül
  • AsyncValue — sealed osztály loading/error/data állapotokkal aszinkron adatokhoz
  • @riverpod kódgenerálás — típusok és provider gyárak automatikus következtetése
  • ProviderScope.overrideWith — izolált tesztelés mock-ok és DI konténerek nélkül
  • Family — paraméterezett provider-ek egyéni gyorsítótárazással
  • autodispose és keepAlive — a provider-ek életciklusának automatikus kezelése

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is