From comment:
Calling this method is equivalent to calling:
Provider.of<T>(context)
WatchContext extension is shortcut for Provider.of(context), but nope, WatchContext extension cannot be used in didChangeDependencies, something like this:
class _ScreenState extends State<Screen> {
int _currentData;
@override
void didChangeDependencies() {
super.didChangeDependencies();
_currentData = context.watch<int>();
}
@override
Widget build(BuildContext context) {
//final _currentData = context.watch<int>();
return Text((_currentData ?? 0).toString());
}
}
This lines
https://github.com/rrousselGit/provider/blob/9c4087abaa753ba5bc15492cf639d97720048cfb/lib/src/provider.dart#L639-L651
must be like this:
assert(
owner.debugBuilding || // <= ADDED
widget is LayoutBuilder ||
widget is SliverWithKeepAliveWidget ||
debugDoingBuild ||
debugIsInInheritedProviderUpdate,
'...');
Exception listing:
โโโโโโโโ Exception caught by widgets library โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The following assertion was thrown building _InheritedProviderScope<int>:
Tried to use `context.watch<int>` outside of the `build` method or `update` callback of a provider.
This is likely a mistake, as it doesn't make sense to rebuild a widget when the value
obtained changes, if that value is not used to build other widgets.
Consider using `context.read<int> instead.
'package:provider/src/provider.dart':
Failed assertion: line 620 pos 9: 'widget is LayoutBuilder ||
widget is SliverWithKeepAliveWidget ||
debugDoingBuild ||
debugIsInInheritedProviderUpdate'
The relevant error-causing widget was:
Provider<int> file:///C:/git/flutter/provider_watch_feature/lib/main.dart:27:49
When the exception was thrown, this was the stack:
#2 WatchContext.watch (package:provider/src/provider.dart:620:9)
#3 _ScreenState.didChangeDependencies (package:provider_watch_feature/main.dart:69:28)
#4 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4833:11)
#5 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4649:5)
#6 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3615:14)
context.owner.debugBuilding || // <= ADDED
No. This flag is true for the entire time the widget tree is building, which is not correct
There is no way to allow didChangeDependencies without allowing everything and that is not worth it imo.
You can use build instead of didChangeDependencies. They are basically the same thing
@rrousselGit but i can use Provider.of(context) something like this.
Why i can't watch shortcut?
Provider.of shouldn't allow it, but it is a breaking change to disallow it.
Provider.of shouldn't allow it, but it is a breaking change to disallow it.
Some people and I use a provider in conjunction with InheritedWidget.
Interaction through didChangeDependencies is the right way to track dependencies and context-based initialization.
Maybe it's worth adding a similar functionality anyway?
https://api.flutter.dev/flutter/widgets/State/didChangeDependencies.html
didChangeDependencies method
Called when a dependency of this State object changes.
For example, if the previous call to build referenced an InheritedWidget that later changed, the framework would call this method to notify this object about the change.
This method is also called immediately after initState. It is safe to call BuildContext.dependOnInheritedWidgetOfExactType from this method.
Subclasses rarely override this method because the framework always calls build after a dependency changes. Some subclasses do override this method because they need to do some expensive work (e.g., network fetches) when their dependencies change, and that work would be too expensive to do for every build.
Works great!

You can use
buildinstead ofdidChangeDependencies. They are basically the same thing

didChangeDependencies is flawed and doesn't do what it claims to do.
There's no guarantee that didChangeDependencies won't be called even if the dependency didn't change. So you cannot safely write:
didChangeDependencies() {
http.get(Something.of(context));
}
Instead, you need to do:
String lastSomething;
didChangeDependencies() {
final something = Something.of(context);
if (lastSomething != something) {
lastSomething = something;
http.get(something);
}
}
This completely kills the purpose of using didChangeDependencies, and build can do the exact same thing:
String lastSomething;
build(context) {
final something = Something.of(context);
if (lastSomething != something) {
lastSomething = something;
http.get(something);
}
}
Similarly, as I said previously, owner.debugBuilding is not a working fix.
I've used it before. You cannot make all of Provider's tests pass with this flag.
@rrousselGit
Do you mean didChangeDependencies deprecated and will be removed from Flutter framework as it has no sense?
In this case it is good idea to make didChangeDependencies case working as described in this issue till didChangeDependencies had not been removed from Flutter framework.
AFAIK didChangeDependencies isn't deprecated. I explained previously how it doesn't do what it is supposed to do, and how therefore supporting didChangeDependencies brings little to no value
@rrousselGit
Thanks for clarification
So didChangeDependencies have sense and use cases - so it have sense to fix this issues as @PlugFox described from my point of view
In other case nice to see new Flutter framework issue to remove didChangeDependencies from the framework
More over current provider issue confuse many developers
and workaround from above is not really solution for this case.
What scenario requires you to use didChangeDependencies? As I said, build is identical to didChangeDependencies in the end.
Supporting didChangeDependencies is not without drawbacks. That would require removing the current assert in its entirety.
@rrousselGit
didChangeDependencies called less times + build is good place for the widgets only, you provided very bad workaround with over-complicate build method.
@rrousselGit
Instead, you need to do:
I can do this through ProxyProvider, IheritedWidget and many other ways, this is not about me.
String lastSomething; build(context) { final something = Something.of(context); if (lastSomething != something) { lastSomething = something; ...You are extremely wrong and teach people extremely bad things.
build method is pure function
https://api.flutter.dev/flutter/widgets/State/build.html
https://en.wikipedia.org/wiki/Pure_function

What scenario requires you to use didChangeDependencies? As I said,
buildis identical todidChangeDependenciesin the end.
didChangeDependencies is not identical build, if it was, it would not exist.
https://flutter.dev/docs/resources/architectural-overview

You are extremely wrong and teach people extremely bad things.
build method is pure function
Google themselves starts side-effects inside build sometimes, such as for list pagination.
The example I gave is a legitimate usage that does not violate how build works.
I've already debated with Googlers about didChangeDependencies too (during the implementation of this assertion in fact) and we agreed that it is flawed. didChangeDependencies is an easy source of bug
Again, as I mentioned before, there is no way to enable didChangeDependencies without breaking some tests.
As proven in https://github.com/rrousselGit/provider/pull/577, the CI does not pass.
@rrousselGit
But Google still keep didChangeDependencies, so it could be nice to take it into account and fix this issue as it break current Flutter framework rules.
Then we could wait until Google remove didChangeDependencies, happy to look into related issue if you already created it.
Closing in favor of #585
I won't be working on #585 soon, but I'm happy to merge a PR that removes the asserts and fix the tests
Most helpful comment
Works great!