Menu
CoddyTech

Provider: Consumer

Part of the State Management section of Coddy's Flutter journey. Lesson 12 of 27.

Here the provider is made inside MyApp's own build, and the same build asks for the lamp right below it. The app shows an error: context belongs to MyApp, which sits above the provider, and a widget can only find providers above it.

A Consumer fixes that. It is a widget, so it sits below the provider, and its builder gets a fresh context and the model itself:

Consumer<Lamp>(
  builder: (context, lamp, child) {
    return Text(lamp.isOn ? 'On' : 'Off');
  },
)

The builder runs again every time the lamp calls notifyListeners(), like a widget that watches it. Inside it, you can call the model's methods straight on lamp: onPressed: () => lamp.toggle().

A Consumer also rebuilds only what it wraps, so wrapping the part that changes keeps the rest of the screen still. In most apps you will use context.watch in a widget of its own, and reach for Consumer when you are in the same build as the provider.

challenge icon

Challenge

Medium

The app opens on an error. Put the lamp's parts inside a Consumer:

  • Wrap the Column in a Consumer<Lamp> and return the Column from its builder.
  • Inside, use the builder's lamp for the icon, the text and the button.

Try it yourself

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

class Lamp extends ChangeNotifier {
  bool _isOn = false;

  bool get isOn => _isOn;

  void toggle() {
    _isOn = !_isOn;
    notifyListeners();
  }
}

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => Lamp(),
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Scaffold(
          appBar: AppBar(title: const Text('Lamp')),
          body: Center(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Icon(
                  context.watch<Lamp>().isOn ? Icons.lightbulb : Icons.lightbulb_outline,
                  size: 96,
                  color: context.watch<Lamp>().isOn ? Colors.amber : Colors.grey,
                ),
                Text(context.watch<Lamp>().isOn ? 'The lamp is on' : 'The lamp is off'),
                const SizedBox(height: 16),
                ElevatedButton(
                  onPressed: () => context.read<Lamp>().toggle(),
                  child: const Text('Switch'),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in State Management

Practice on your own: Online Flutter compiler