Skip to content

Intermediate · State management · topic 29 of 50 · 30 min

Riverpod overview

Explanation

Riverpod is a state management library by the author of Provider, designed to be compile-safe, testable and independent of the widget tree. You wrap the app in ProviderScope, declare providers as global, immutable definitions, and read them with ref.watch and ref.read in ConsumerWidgets. Notifier classes hold changeable state, and FutureProvider handles async data with loading, error and data states. Riverpod 3 changed some APIs, so check riverpod.dev for current syntax.

Why Riverpod?

Provider is simple, but it depends on the widget tree: reading a provider that is not above you fails at run time, and two providers of the same type are awkward. Riverpod, created by the same author (Remi Rousselet), fixes these: providers are declared once as top-level definitions, missing providers are compile errors rather than run-time crashes, and state can be read and tested without a BuildContext.

Think of it like this: Provider is like keeping important documents in a specific room of your house: anyone in that room can read them, but someone in the wrong room cannot. Riverpod is like keeping them in a bank locker system: every document has an exact locker number known in advance, and anyone with the key (ref) can get it from anywhere.

The core pieces

PieceRole
ProviderScopeWraps the app; stores the state of all providers
ProviderExposes a value that does not change by itself (a repository, a formatter)
NotifierProvider + NotifierHolds state that changes through methods (a cart, a counter)
FutureProvider / AsyncNotifierProviderLoads async data and exposes AsyncValue: loading, error or data
ref.watch / ref.readListen and rebuild / read once in callbacks
ConsumerWidgetA widget that receives a WidgetRef to read providers

Providers in Riverpod are lazy and cached: a provider runs only when something first reads it, and its value is kept while something is listening. Providers can also read other providers with ref.watch inside their own definition, so a cart total provider can depend on the cart provider and update whenever the cart changes.

A counter with a Notifier

dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class CartCount extends Notifier<int> {
  @override
  int build() => 0;                      // initial state

  void add() => state = state + 1;       // assigning state notifies listeners
}

final cartCountProvider = NotifierProvider<CartCount, int>(CartCount.new);

void main() => runApp(const ProviderScope(child: MaterialApp(home: CartScreen())));

class CartScreen extends ConsumerWidget {
  const CartScreen({super.key});
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(cartCountProvider);
    return Scaffold(
      body: Center(child: Text('Items: $count')),
      floatingActionButton: FloatingActionButton(
        onPressed: () => ref.read(cartCountProvider.notifier).add(),
        child: const Icon(Icons.add),
      ),
    );
  }
}
state is immutable: assign a new value instead of changing it in place. Syntax follows the official docs; check riverpod.dev for the current version.

Async data with FutureProvider

dart
final weatherProvider = FutureProvider<String>((ref) async {
  await Future.delayed(const Duration(seconds: 1));      // pretend API call
  return 'Pune: 31°C';
});

class WeatherText extends ConsumerWidget {
  const WeatherText({super.key});
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final weather = ref.watch(weatherProvider);
    return weather.when(
      data: (w) => Text(w),
      loading: () => const CircularProgressIndicator(),
      error: (e, st) => Text('Could not load: $e'),
    );
  }
}
AsyncValue.when forces you to handle loading, error and data.

Code generation (optional)

Riverpod also offers an optional code-generation style with @riverpod annotations and the riverpod_generator package, which writes provider declarations for you. Many teams use it; it is not required to start. Riverpod 3.0 (released in 2025) changed and simplified several APIs, and older tutorials may use outdated names such as StateNotifierProvider; follow riverpod.dev for current syntax.

Common mistakes

  • Forgetting ProviderScope at the root: an error on the first read.
  • Using ref.watch inside callbacks: use ref.read there.
  • Mutating state in place (state.add(item)) in a Notifier: listeners are not notified. Assign a new value (state = [...state, item]).
  • Copying old Riverpod 1.x/2.x tutorials without checking the current API.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Riverpod overview · 1/6

Riverpod

Riverpod is by the author of Provider. It is compile safe, testable and does not depend on the widget tree.

Prefer a video by a teacher? Find free videos on “riverpod tutorial notifier provider consumerwidget asyncvalue” on YouTube ↗

In real life: A city weather card that loads itself

A farming advice app shows the weather for the farmer's district at the top of the home screen. A FutureProvider calls the weather API; the card uses weather.when to show a spinner, the result, or a friendly error. Pull-to-refresh calls ref.invalidate(weatherProvider) to load fresh data. Tests override the provider with fake data, without any network.

dart
// Refresh:
RefreshIndicator(
  onRefresh: () => ref.refresh(weatherProvider.future),
  child: ListView(children: const [WeatherText()]),
)
ref.refresh re-runs the provider and returns its new Future.

Practice (0/3 done)

Task 1 · Question

What must wrap a Riverpod app?

Task 2 · Question

In a Notifier<List<String>>, which update notifies listeners correctly?

Task 3 · Practice

Rebuild the Provider cart from the previous topic with Riverpod: a Notifier<List<CartItem>> with add and clear, a NotifierProvider, ConsumerWidgets for the badge and the cart screen, and a FutureProvider that "loads" products after a delay with loading and error states. Follow the syntax on riverpod.dev for the version you install.

Quick quiz

Question 1

1.Who created Riverpod?

Question 2

2.What does AsyncValue.when require you to handle?

Question 3

3.Which widget type gives you a WidgetRef in build?

Question 4

4.Why check riverpod.dev before copying an old tutorial?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Who created Riverpod?

Answer: The author of Provider

Remi Rousselet created both.

What does AsyncValue.when require you to handle?

Answer: data, loading and error

All three states.

Which widget type gives you a WidgetRef in build?

Answer: ConsumerWidget

build(BuildContext context, WidgetRef ref).

Why check riverpod.dev before copying an old tutorial?

Answer: APIs changed across major versions, including Riverpod 3

Use current syntax.

Which object holds a StatefulWidget's State between rebuilds?Related

Answer: The element

Elements are long-lived.

From Interview questions: Flutter

Which class do Provider models usually extend?Related

Answer: ChangeNotifier

ChangeNotifier has addListener and notifyListeners.

From Provider and ChangeNotifier

What should you do before starting a freelance app project?Related

Answer: Agree a written scope, timeline and payment milestones

Clear scope prevents disputes.

From Flutter jobs and freelancing in India

What is good advice about state management choices?Related

Answer: Pick one, learn it well, use it consistently

Consistency matters most.

From Bloc, Cubit and choosing an approach

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 1 more topic in “State management” before its exam: Bloc, Cubit and choosing an approach.
  2. Module 7 exam: State management · 12 questions · 25 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, Networking, storage and Firebase. 50 topics left in the course before the final exam.

← Previous: Provider and ChangeNotifier