Provider
02 / 02

Provider Fundamentals: ChangeNotifier, Consumer & Access

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