Search code examples
flutterdartflutter-provider

Consumer and context.watch in MultiProvider


I am trying Flutter for the first time, and I am a little confused by the MultiProvider class.

The question is straightforward, but I didn't find an explanation:

when should one use Consumer and when context.watch?

For instance, taking one of the examples apps I have found, I tried using two providers for two global states, the theme and the status of the app:

runApp(
  MultiProvider(providers: [
    ChangeNotifierProvider(create: (context) => AppTheme()),
    ChangeNotifierProvider(create: (context) => AppStatus()),
  ],
  child: const MyApp()
  ));

Then the app widget accesses the theme with Consumer:

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

  @override
  Widget build(BuildContext context) {
    return Consumer<AppTheme>(
      builder: (context, appTheme, child) {
        // ...

As far as I understand, now all children widgets will inherit the provider. Is it right?

My home page, then, called by the MyApp class does not use Consumer, but context.watch:

@override
Widget build(BuildContext context) {
  final appTheme = context.watch<AppTheme>();
  final appStatus = context.watch<AppStatus>();
  return NavigationView( 
    // ...

It works, don't get me wrong, but I just copied the row above my appStatus, so I don't really fully understand it. This is also due to another screen that I've concocted to access the AppStatus global state, but I use Consumer, as suggested by the Flutter documentation:

class _ViewerState extends State<Viewer> {

  @override
  Widget build(BuildContext context) {
    return Consumer<AppStatus>(
      builder: (context, appStatus, child) {
        return ScaffoldPage.scrollable(
          header: const PageHeader(title: Text('Test')),
          children: [
            FilledButton(child: Text("Try ${appStatus.count}"), onPressed: (){ appStatus.increment(); debugPrint('pressed ${appStatus.count}'); }),
            FilledButton(child: Text("Reset"), onPressed: (){ appStatus.reset(); }),
          ]);
      },
    );
  }
}

I have the feeling that I am misusing something here, and I do not really understand what's going on under the hood...


Solution

  • context.watch<T>() and Consumer<T> does the same thing. Most of the time context.watch<T>() is just more convenient. In some cases where context is not available Consumer<T> is useful.