14
// Are these the same?
final model = Provider.of<Model>(context, listen: false); 
final model = context.read<Model>(); 

// Are these the same?
final model = Provider.of<Model>(context);
final model = context.watch<Model>();

Are they the same or aren't they? If they are, then why do I get this error when I use read inside the build() method, while Provider.of() works?

Tried to use context.read<Model> inside either a build method or the update callback of a provider.

Boann
  • 48,794
  • 16
  • 117
  • 146
iDecode
  • 22,623
  • 19
  • 99
  • 186

3 Answers3

33

final model = context.read<Model>();
This returns the Model without listening for any changes.

final model = context.watch<Model>();
This makes the widget listen for changes on the Model.

final model = Provider.of<Model>(context, listen: false);
This works the same as context.read<Model>();

final model = Provider.of<Model>(context);
This works the same as context.watch<Model>();

Recommendations:
Use context.read(), context.watch() instead of Provider.of(). For more insights, refer to this, this & this.

Boann
  • 48,794
  • 16
  • 117
  • 146
Sanket Vekariya
  • 2,848
  • 3
  • 12
  • 34
  • 2
    I am sure you must have read the question carefully before answering. -1 from me, sorry!!! – iDecode Jun 12 '20 at 07:33
  • The default value of listen = true when you do not specify in Provider.of(). If you want to get updated data, you must use a "watch" instead or "read". – Sanket Vekariya Jun 12 '20 at 07:46
  • First, I didn't ask about the default value of `listen`, second, I didn't want to get the updated data. I again suggest you to read the question carefully before answering. Thanks – iDecode Jun 12 '20 at 11:41
  • I didn't though. Can you kindly share any example what you want to achieve and what you are getting currently? It seems the question can lead to some misunderstanding. If possible! – Sanket Vekariya Jun 12 '20 at 15:07
  • Well I am currently using FirebaseAuth as my model, when I use `Provider.of(...)` with `listen: false`, it works but when I use `read`, it fails. – iDecode Jun 12 '20 at 15:43
  • I have added my own answer, you can take a look now. – iDecode Jun 12 '20 at 16:05
14

Well, they aren't the same.

You shouldn't use read inside the build method. Instead stick to the old is gold pattern:

final model = Provider.of<Model>(context, listen: false); 

read is used when you want to use the above pattern in a callback, for instance, when a button is pressed, then we can say they both are performing the same action.

onPressed: () {
  final model = context.read<Model>(); // recommended
  final model = Provider.of<Model>(context, listen: false); // works too
}
Boann
  • 48,794
  • 16
  • 117
  • 146
iDecode
  • 22,623
  • 19
  • 99
  • 186
  • 1
    now it would be interesting to know, why does the documentation recommend against using context.read() in a build method .... – Wecherowski Aug 08 '21 at 12:03
  • 1
    @Wecherowski In [this](https://stackoverflow.com/a/62434596/6753606) answer, Remi explains why `context.read` must not be used in build method. But I must say that I'm not convinced by it. – SametSahin Sep 04 '21 at 12:01
2

context.read<T>() internally returns Provider.of<T>(context, listen: false).

For the moment, use whichever you think is best or the one you prefer.

This is the implementation of read in Provider:

extension ReadContext on BuildContext {
  T read<T>() {
    return Provider.of<T>(this, listen: false);
  }
}
Alex
  • 159
  • 2
  • 7