Home About Skills Products Work
Projects Services Experience
Learn
Tutorials Courses Blogs Resources
Contact
Blog · Mobile Development

State Management in Flutter: Provider vs Riverpod

State Management in Flutter: Provider vs Riverpod
Advertisement

Flutter's built-in setState works fine for a single screen, but any real app needs a way to share state across multiple, unrelated widgets — a logged-in user, a shopping cart, a theme preference. Provider and Riverpod are the two most common answers, and they solve the same problem differently enough to matter.

Provider: The Established Choice

class CartModel extends ChangeNotifier {
  final List<Item> _items = [];
  List<Item> get items => _items;

  void add(Item item) {
    _items.add(item);
    notifyListeners(); // tells every listening widget to rebuild
  }
}
// Register it above the widgets that need it
ChangeNotifierProvider(create: (_) => CartModel(), child: MyApp());

// Read it anywhere below
final cart = context.watch<CartModel>();

context.watch rebuilds the widget when notifyListeners() fires; context.read reads the current value once, without subscribing to future changes — useful inside a button's onPressed, where you don't want a rebuild.

Riverpod: Provider's Successor

Riverpod (by the same author as Provider) fixes several structural issues: providers are declared outside the widget tree entirely, so they're accessible without a BuildContext, fully testable in isolation, and compile-time safe against the classic "no provider found" runtime error.

final cartProvider = StateNotifierProvider<CartNotifier, List<Item>>(
  (ref) => CartNotifier(),
);

class CartNotifier extends StateNotifier<List<Item>> {
  CartNotifier() : super([]);

  void add(Item item) {
    state = [...state, item]; // new list — Riverpod compares by reference
  }
}
class CartScreen extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final items = ref.watch(cartProvider);
    return ListView(children: items.map((i) => Text(i.name)).toList());
  }
}

The Key Practical Difference

Provider relies on BuildContext to find providers up the widget tree — simple, but it means providers can't easily be read from outside a widget (a background service, for example). Riverpod's providers are just global, statically-analyzable objects — no context needed anywhere, which is also why Riverpod catches "provider not found" mistakes at compile time instead of at runtime.

Which One to Pick

For a new project today, Riverpod is the safer long-term choice — better testability, no context dependency, and active development from its author. Provider is still perfectly reasonable for a smaller app or when working in an existing codebase already built on it; migrating an established app for its own sake is rarely worth the churn.

Flutter for Beginners: Building Your First Cross-Platform App

Flutter for Beginners: Building Your First Cross-Platform App

Widgets, StatelessWidget vs StatefulWidget, layout basics, and calling a REST API — everything needed to build a first real Flutter screen.

Esc