Riverpod — en kompilerbar tillstånds- och beroendehanterare för Flutter, skapad av Rémi Roussel 2021 som efterträdare till Provider. Riverpod löser Providers grundläggande problem: brist på kompileringskontroll, beroende av BuildContext och svårigheter med ProviderNotFoundException. Enligt data från pub.dev har paketet samlat över 5 tusen gillamarkeringar och ersätter aktivt Provider i nya projekt.
Huvudpunkter
Riverpod — ett bibliotek för tillståndshantering och beroendeinjektion i Flutter som kompilerar providerbeskrivningar till säker Dart-kod. Till skillnad från Provider är Riverpod-providers inte bundna till BuildContext: de skapas globalt eller i ProviderScope och är tillgängliga var som helst. Kompilatorn kontrollerar typer, beroenden och integriteten hos providergrafen under byggfasen, vilket eliminerar runtime-fel som ProviderNotFoundException.
Riverpod använder override-modellen för testning: varje provider kan åsidosättas via ProviderScope.overrideWith utan att behöva skapa underklasser eller mocka gränssnitt. Detta gör testning isolerad: varje test får sin egen kopia av beroendegrafen som är fullständigt kontrollerad.
Enligt Flutter Community Survey 2025 ligger Riverpod på tredje plats i popularitet efter Provider och BLoC. Samtidigt är Riverpod det snabbast växande paketet: +120% installationer under 2024. Huvudskäl: kompileringssäkerhet, frånvaro av ProviderNotFoundException, inbyggt stöd för asynkronitet via AsyncValue.
Riverpod tillhandahåller 8 typer av providers, var och en för ett specifikt scenario: Provider (konstant/tjänst), StateProvider (primitivt tillstånd), StateNotifierProvider (komplex logik med StateNotifier), ChangeNotifierProvider (för migrering från Provider), FutureProvider (asynkron data, en gång), StreamProvider (reaktiv ström), NotifierProvider (nytt API, Flutter 3.10+) och AsyncNotifierProvider (asynkron Notifier).
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 — objektet som skickas till varje provider för åtkomst till andra providers. ref.watch — prenumerera på ändringar, ref.read — engångsläsning, ref.invalidate — återställa cache. ProviderRef ersätter BuildContext från Provider: vilken provider som helst kan läsa andra providers utan åtkomst till widgetträdet. Detta gör det möjligt att bygga beroendegrafen utanför UI-lagret.
ProviderScope — den obligatoriska rotwidgeten för Riverpod. ProviderScope lagrar alla providers, hanterar deras livscykel och cachar värden. Utan ProviderScope kommer applikationen att krascha med ProviderNotFoundException. ProviderScope kan vara nästlat — ett nästlat scope åsidosätter förälderns providers, vilket används för testning och funktionsisolering.
AsyncValue — en sealed-klass i Riverpod för att representera asynkront tillstånd. AsyncValue har tre varianter: AsyncData (lyckad data), AsyncError (fel), AsyncLoading (laddar). Istället för manuell växling mellan loading/error/data returnerar varje FutureProvider eller StreamProvider automatiskt AsyncValue, och widgeten hanterar alla tre tillstånden via ref.watch.
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 — metod för mönstermatchning av alla tre tillstånden. Kompilatorn kontrollerar att alla tre fall hanteras — om loading eller error glöms bort kommer koden inte att kompilera. AsyncValue.whenData — endast för data (om loading/error inte behövs). AsyncValue.guard — ett try-catch-omslag för att konvertera undantag till AsyncError. keepAlive — en flagga som förhindrar förstöring av providercachen vid utträde ur synlighetsomfånget.
Kodgenerering — en nyckelfunktion i Riverpod 2.0+. Annoteringen @riverpod ovanför en funktion genererar automatiskt en provider med rätt typ, stöd för refaktorisering och autokomplettering. Kodgenerering använder riverpod_generator och build_runner. Utvecklaren skriver en ren funktion och allt annat — typer, klasser, fabrikskonstruktorer — genereras automatiskt.
@riverpod
String helloWorld(HelloWorldRef ref) {
return 'Hello World';
}
// Genererad: final helloWorldProvider = Provider((ref) => 'Hello World');
@riverpod
class Counter extends _$Counter {
int build() => 0;
void increment() => state++;
}Notifier — ett nytt API för föränderligt tillstånd med kodgenerering. Notifier är en klass med en build()-metod och metoder för att ändra tillstånd. Till skillnad från StateNotifier kräver Notifier ingen separat tillståndsklass och ger direkt åtkomst till state via getter/setter. Riverpod genererar automatiskt NotifierProvider för varje Notifier-klass med annoteringen @riverpod.
build_runner: kodgenerering startas med kommandot dart run build_runner build. Genererade filer har suffixet .g.dart och importeras till källkoden. När annoteringar eller providertyper ändras måste kodgenereringen startas om. Riverpod 2.x rekommenderar kodgenerering för alla nya projekt — manuell skapande av providers blir föråldrad.
Huvudskillnader mellan Riverpod och Provider: oberoende av BuildContext, kompileringssäkerhet, inbyggt arbete med asynkronitet, automatisk cachning och testning via override. Provider kräver BuildContext för åtkomst till tillstånd (context.watch, context.read), Riverpod använder WidgetRef och globalt deklarerade providers.
| Egenskap | Provider | Riverpod |
|---|---|---|
| Beroende av BuildContext | Ja | Nej |
| Kompileringskontroll | Nej | Ja (via @riverpod) |
| ProviderNotFoundException | Runtime | Omöjlig |
| Asynkronitet | Manuell | AsyncValue (inbyggd) |
| Testning | Omslag i Provider | ProviderScope.overrideWith |
| Cachning | Nej | Automatisk + keepAlive |
Migrering från Provider: Riverpod stöder ChangeNotifierProvider.adaptive för användning av befintliga ChangeNotifier utan omskrivning. Stegvis migrering: först skrivs nya funktioner med Riverpod, sedan ersätts gamla Providers med Riverpod-providers via en adapter. Båda paketen kan samexistera i samma projekt, vilket möjliggör migrering utan att frysa utvecklingen.
Testning av Riverpod bygger på ProviderScope.overrideWith. Varje provider åsidosätts inom test-ProviderScopet utan mockar och DI-containrar. ProviderContainer — en isolerad miljö för tester utan Flutter (ren Dart), vilket möjliggör testning av providers utan att rendera widgets.
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 — utan Flutter. Använd ProviderContainer för enhetstester av providers utan widgets. overrideWithValue — ersättning av provider med ett specifikt värde. overrideWith — ersättning med en providerfabrik (för mockning av tjänster). autodispose — i tester, kontrollera att providern förstörs vid utträde ur synlighetsomfånget med container.dispose().
Vanliga frågor
Riverpod — ett tillståndshanteringsbibliotek med globala providers, AsyncValue och kodgenerering. BLoC — ett arkitekturmönster med Event → Stream → State. Riverpod är lättare att lära sig och har bättre DX genom @riverpod-annoteringar. BLoC ger strikt isolering av affärslogik och Event-spårning via BlocObserver. Valet beror på projektets paradigm: Riverpod är närmare Provider, BLoC — reaktiva strömmar.
Autodispose — mekanismen för automatisk förstöring av en provider när ingen prenumererar på den. Som standard är alla Riverpod-providers autodispose: när widgeten lämnar trädet tas providern bort från minnet. keepAlive — en flagga som inaktiverar autodispose för providers som alltid måste leva (API-klienter, repositories, inställningar). Detta förhindrar minnesläckor — oanvända providers förstörs automatiskt.
ref.invalidate — en metod som tvingar återställning av providerns cache. Efter invalidate återskapas providern vid nästa läsning: FutureProvider kör om async-funktionen, StreamProvider prenumererar igen på strömmen. Använd invalidate för tvingad uppdatering av data (pull-to-refresh, användarbyte). ref.refresh — en kombination av invalidate + läsning: återställer och läser omedelbart det nya värdet i en operation.
Ja. Riverpod 1.x fungerar endast utan kodgenerering — providers skapas manuellt via Provider(), StateNotifierProvider(), FutureProvider() etc. Riverpod 2.x stöder båda metoderna. Utan kodgenerering finns mer boilerplate, men inget beroende av build_runner och dart run build_runner build. För små projekt (upp till 30 providers) är manuellt skapande motiverat, för stora projekt är kodgenerering obligatoriskt.
Family — en modifierare för provider som accepterar en extern parameter. Till exempel userProvider(123) — en provider som laddar användaren med ID 123. Family-providers cachar resultatet för varje unik parameter separat. Använd Family för en lista med element där varje element laddas efter ID. Family-modifieraren finns för alla providertyper: Provider.family, FutureProvider.family, StreamProvider.family.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också