Provider: ChangeNotifier, Consumer & Access
Provider is a Flutter state management library built as a convenience wrapper around InheritedWidget -- Flutter's underlying, efficient mechanism for propagating data down the widget tree. Provider abstracts away InheritedWidget's boilerplate behind a simpler, more ergonomic API.
ChangeNotifier & ChangeNotifierProvider
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';
class CartModel extends ChangeNotifier {
final List<Item> _items = [];
int get itemCount => _items.length;
void addItem(Item item) {
_items.add(item);
notifyListeners(); // triggers listening widgets to rebuild
}
}
// Provides a CartModel instance to the widget tree
ChangeNotifierProvider(
create: (_) => CartModel(),
child: MyApp(),
)Consumer: Scoped Rebuilds
// Wraps just the Text that needs to rebuild -- not the whole parent
Consumer<CartModel>(
builder: (context, cart, child) => Text('${cart.itemCount} items'),
)
// Selector rebuilds ONLY when the selected piece changes -- more
// granular than Consumer, which rebuilds on ANY change to CartModel
Selector<CartModel, int>(
selector: (_, cart) => cart.itemCount,
builder: (_, count, __) => Text('$count'),
)read() vs. watch()
// context.read<T>() -- no subscription, appropriate in a callback
ElevatedButton(
onPressed: () => context.read<CartModel>().addItem(item),
child: Text('Add to cart'),
)
// context.watch<T>() -- subscribes, rebuilds THIS ENTIRE widget on change
// (calling it in a large build() method rebuilds more than necessary --
// prefer Consumer/Selector to scope the rebuild narrowly)
build(BuildContext context) {
final count = context.watch<CartModel>().itemCount;
return Text('$count');
}MultiProvider
// Avoids deeply nested provider widgets
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CartModel()),
Provider(create: (_) => AuthService()), // read-only, non-changing
],
child: MyApp(),
)Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free