When to use Provider.of<X> vs. Consumer<X> in Flutter

FlutterDartFlutter Provider

Flutter Problem Overview


I'm still wrapping my head around state-management techniques in flutter and am a bit confused about when and why to use Provider.of<X> vs. Consumer<X>. I understand (I think) from the documentation that when choosing between these two you would use Provider.of when we want access to the data, but you don't need the UI to change. So the following (taken from the docs) gets access to the data and updates the UI on new events:

return HumongousWidget(
  // ...
  child: AnotherMonstrousWidget(// <- This widget will rebuild on new data events
    // ...
    child: Consumer<CartModel>(
      builder: (context, cart, child) {
        return Text('Total price: ${cart.totalPrice}');
      },
    ),
  ),
);

Whereas, where we only need the data on don't want to rebuild with UI, we'd use Provider.of<X> with the listen parameter set to false, as below:

Provider.of<CartModel>(context, listen: false).add(item); \\Widget won't rebuild

However, listen isn't required and so the following will run too:

Provider.of<CartModel>(context).add(item); \\listener optional

So this brings me to a few questions:

  1. Is this the correct way to distinguish Provider.of<X> and Consumer<X>. Former doesn't update UI, latter does?
  2. If listen isn't set to false will the widget be rebuilt by default or not rebuilt? What if listen is set to true?
  3. Why have Provider.of with the option to rebuild the UI at all when we have Consumer?

Flutter Solutions


Solution 1 - Flutter

It doesn't matter. But to explain things rapidly:

Provider.of is the only way to obtain and listen to an object. Consumer, Selector, and all the *ProxyProvider calls Provider.of to work.

Provider.of vs Consumer is a matter of personal preference. But there's a few arguments for both

Provider.of
  • can be called in all the widgets lifecycle, including click handlers and didChangeDependencies
  • doesn't increase the indentation
Consumer
  • allows more granular widgets rebuilds
  • solves most BuildContext misuse

Solution 2 - Flutter

Provider.of<>

applying provider, whole widget will rebuild if listen true.

Consumer<>

using consumer only specifically allowed widget will rebuild.

Solution 3 - Flutter

For your questions:

  1. Is this the correct way to distinguish Provider.of<X> and Consumer<X>. Former doesn't update UI, latter does?

Provider.of<X> depends on value of listen to trigger a new State.build to widgets and State.didChangeDependencies for StatefulWidget.

Consumer<X> always update UI, as it uses Provider.of<T>(context), where listen is true. See full source here.

  1. If listen isn't set to false will the widget be rebuilt by default or not rebuilt? What if listen is set to true?

Default value is true, means will trigger a new State.build to widgets and State.didChangeDependencies for StatefulWidget. See full source here.

static T of<T>(BuildContext context, {bool listen = true}).

  1. Why have Provider.of with the option to rebuild the UI at all when we have Consumer?

Pretty much covered by Rémi Rousselet's answer.

Solution 4 - Flutter

There should not be any performance concern by using it, moreover, we should use consumers if we want to change some specific widget only on screen. This is the best approach I can say in terms of coding practice.

 return Container(
    // ...
    child: Consumer<PersonModel>(
      builder: (context, person, child) {
        return Text('Name: ${person.name}');
      },
    ),
  );

Like in the above example, we are only required to update the value of the Single Text Widget so add consumers there instead of Provider which is accessible to other widgets as well.

Note: Consumer or Provider update the only reference of your instance which widgets are using, if some widgets are not using then it will not re-drawn.

Solution 5 - Flutter

The widget Consumer doesn't do any fancy work. It just calls Provider.of in a new widget, and delegate its build implementation to [builder]. It's just syntactic sugar for Provider.of but the funny thing is I think Provider.of is simpler to use.

Look at this article for more clearance https://blog.codemagic.io/flutter-tutorial-provider/

Solution 6 - Flutter

We have 3 things to understand here.

> When you wrap Provider around a widget it sets up a reference to a widget tree and a variable whose changes you want to refer to.

using Provider.of(context) you can get access to the variable you want to monitor and make changes in it.

> Provider.of(context) with and without listen gives you a reference to the above-declared Provider object and a widget tree where it can be accessed from. But as said by others, it rebuild the whole widget tree it sits on top of when listen is not false.

In the end, you can use consumer to monitor any changes that happened using the above step

> The consumer acts like a more granular listener and be applied to a fixed widget to help avoid unnecessary rebuilds.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOprimusView Question on Stackoverflow
Solution 1 - FlutterRémi RousseletView Answer on Stackoverflow
Solution 2 - FlutterMijanur RahmanView Answer on Stackoverflow
Solution 3 - FlutterLee Chee KiamView Answer on Stackoverflow
Solution 4 - FlutterJitesh MohiteView Answer on Stackoverflow
Solution 5 - FlutterSachinView Answer on Stackoverflow
Solution 6 - FlutterSaurabh KumarView Answer on Stackoverflow