I stumbled upon a problem when using a Provider. It was error-prone to use the Provider instance inside initState().
@override
void initState() {
// TODO: implement initState
super.initState();
provider = Provider.of<SomeChangeNotifier>(context);
}
When I tried to initialize a Provider instance inside it like the code above, an error was shown.
dependOnInheritedWidgetOfExactType<_InheritedProviderScope<SomeChangeNotifier?>>() or dependOnInheritedElement() was called before _WidgetState.initState() completed.
Thus, the Provider should be initialized inside build() method. Then the problem is how to call method that should be called only once when we cannot use Provider inside initState().
The solution was to scedule a call at the end of the frame inside initState(). Using the Provider instance inside initState isn't possible, because it's initialized inside build(). But, if the call could wait until the end of the frame, the instance should be accessible. This is where the WidgetBinding and addPostFrameCallback comes in.
void initState() {
// TODO: implement initState
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
provider.someMethod();
});
}
The addPostFrameCallback makes the call at the end of the frame which makes the Provider access possible. I don't know if build() call could happen after this post frame callback. At least it didn't happened while I was testing. I think this might have potential to make some errors.
Above code works fine, although There's another solution that seems a bit safer.
void initState() {
// TODO: implement initState
super.initState();
Provider.of<SomeChangeNotifier>(context, listen: false).someMethod();
}
Well, you can just use it like this. Getting a Provider instance is not allowed, but somehow calling a method without getting an instance was ok. I guess I have a lot of things to learn about flutter.
https://api.flutter.dev/flutter/widgets/WidgetsBinding-mixin.html
https://api.flutter.dev/flutter/scheduler/SchedulerBinding/addPostFrameCallback.html