What's the difference between doing context.watch vs using a Consumer widget?

100 Views Asked by At

What is the difference between using context.watch<Counter>().count from the example on the Provider package page and using a Consumer widget when trying to use the provider values?

Using context.watch().count to get the current value:

class Count extends StatelessWidget {
  const Count({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text(
      /// Calls `context.watch` to make [Count] rebuild when [Counter] changes.
      '${context.watch<Counter>().count}',
      key: const Key('counterState'),
      style: Theme.of(context).textTheme.headlineMedium,
    );
  }
}

Using a Consumer widget:

class Count extends StatelessWidget {
  const Count({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Consumer<Counter>(
      builder: (context, value, child) {
        return Text(value.count);
      }
    );
  }
}

Counter class:

class Counter with ChangeNotifier, DiagnosticableTreeMixin {
  int _count = 0;

  int get count => _count;

  void increment() {
    _count++;
    notifyListeners();
  }

  /// Makes `Counter` readable inside the devtools by listing all of its properties
  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(IntProperty('count', count));
  }
}
1

There are 1 best solutions below

1
Rémi Rousselet On

Effectively nothing.
Consumer is doing nothing outside of calling context.watch and sending that to builder.

The main reason Consumer exists is:

  • It can easily be placed over a specific widget in the widget-tree. This enables rebuilding only said widget when the provider changes – without having to create a custom Stateless/StatefulWidget.
  • If a widget creates a Provider and directly wants to consume it, their BuildContext likely wouldn't have access to the Provider. Using Consumer solves this problem as it would be under the Provider.
  • It can be used inside MultiProvider if you want to have more advanced provider logic.