Riverpod — essensen, kompilering av beroenden i Flutter

Författare: IT Sectr Publicerad: 2026-02-19 Lästid: 7 min

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

  • ProviderRef — objekt för åtkomst till andra providers inuti en provider
  • AsyncValue — omslag för asynkron data med tillstånden loading/error/data
  • Notifier — klass för föränderligt tillstånd med ändringsmetoder
  • ProviderScope — rotwidget som hanterar alla providers
  • Code Generation — @riverpod-annoteringar för automatisk generering av providers

Vad är Riverpod?

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.

Typer av providers

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).

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 — 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 och arbete med asynkronitet

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.

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 — 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.

Code Generation och @riverpod

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.

Dart
@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.

Riverpod vs Provider

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.

EgenskapProviderRiverpod
Beroende av BuildContextJaNej
KompileringskontrollNejJa (via @riverpod)
ProviderNotFoundExceptionRuntimeOmöjlig
AsynkronitetManuellAsyncValue (inbyggd)
TestningOmslag i ProviderProviderScope.overrideWith
CachningNejAutomatisk + 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.

Testa Riverpod

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.

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 — 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

Vad skiljer Riverpod från BLoC?

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.

Vad är autodispose i Riverpod?

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.

Hur fungerar ref.invalidate?

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.

Kan Riverpod användas utan kodgenerering?

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.

Vad är Family-providers?

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

  • Riverpod — kompilerbar tillståndshanterare, efterträdare till Provider utan ProviderNotFoundException
  • ProviderRef — ersättare för BuildContext för åtkomst till providers inuti andra providers
  • AsyncValue — sealed-klass med tillstånden loading/error/data för asynkron data
  • Kodgenerering @riverpod — automatisk typinferens och providerfabriker
  • ProviderScope.overrideWith — isolerad testning utan mockar och DI-containrar
  • Family — parametriserade providers med individuell cachning
  • autodispose och keepAlive — automatisk hantering av providers livscykel

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.

Diskutera projektet

Läs också