The problem here lies with the fact that context
does not exist yet in initState
as extensively explained by the other answers. It doesn't exist because it hasn't yet been made a part of the widget tree.
Calling a method
If you're not assigning any state and only calling a method then initState
would be the best place to get this done.
// The key here is the listen: false
Provider.of<MyProvider>(context, listen: false).mymethod();
The code above is allowed by Flutter because it doesn't have to listen for anything. In short, it's a one off. Use it where you only want to do something instead of read/listen to something.
Listening to changes
Alternatively, if you need to listen to changes from Provider then the use of didChangeDependencies
would be the best place to do so as context
would exist here as in the docs.
This method is also called immediately after initState.
int? myState;
@override
void didChangeDependencies() {
// No listen: false
myState = Provider.of<MyProvider>(context).data;
super.didChangeDependencies();
}
If you've never used didChangeDependencies
before, what it does is get called whenever updateShouldNotify()
returns true. This in turn lets any widgets that requested an inherited widget in build()
respond as needed.
I'd usually use this method in a FutureBuilder
to prevent reloading data when data already exists in Provider after switching screens. This way I can just check Provider for myState
and skip the preloader (if any) entirely.
Hope this helps.