I am calling initial method to load data from API using initState. But it is resulting me an error. Here is error:
Unhandled Exception: inheritFromWidgetOfExactType(_LocalizationsScope) or inheritFromElement() was called before _ScreenState.initState() completed.
When an inherited widget changes, for example if the value of Theme.of() changes, its dependent widgets are rebuilt. If the dependent widget's reference to the inherited widget is in a constructor or an initState() method, then the rebuilt dependent widget will not reflect the changes in the inherited widget.
My code is:
@override
void initState() {
super.initState();
this._getCategories();
}
void _getCategories() async {
AppRoutes.showLoader(context);
Map<String, dynamic> data = await apiPostCall(
apiName: API.addUser,
context: context,
parameterData: null,
showAlert: false,
);
if(data.isNotEmpty){
AppRoutes.dismissLoader(context);
print(data);
}else {
AppRoutes.dismissLoader(context);
}
}
You need to call _getCategories
after initState
has completed.
@override
void initState() {
super.initState();
Future.delayed(Duration.zero, () {
this._getCategories();
});
// Could do this in one line: Future.delayed(Duration.zero, this._getCategories);
}
Also, you could do this on a different way, using addPostFrameCallback. To make this task easier, you could create a mixin to be added to StatefulWidgets.
mixin PostFrameMixin<T extends StatefulWidget> on State<T> {
void postFrame(void Function() callback) =>
WidgetsBinding.instance?.addPostFrameCallback(
(_) {
// Execute callback if page is mounted
if (mounted) callback();
},
);
}
Then, you just need to plug this mixin to you page, like that:
class _MyPageState extends State<MyPage> with PostFrameMixin {
@override
void initState() {
super.initState();
postFrame(_getCategories);
}
}
Use the didChangeDependencies method which gets called after initState.
For your example:
@override
void initState() {
super.initState();
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
this._getCategories();
}
void _getCategories() async {
// Omitted for brevity
// ...
}
Adding a frame callback might be better than using Future.delayed
with a zero duration - it's more explicit and clear as to what is happening, and this kind of situation is what frame callback was designed for:
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
_getCategories();
});
}
an alternative is to put it inside PostFrameCallback
which is between initState
and Build
.
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback((_) => getData());
super.initState();
}
getData() async {
}
There are many ways to solve this problem, override initState
method:
@override
void initState() {
super.initState();
// Use any of the below code here.
}
Using SchedulerBinding
mixin:
SchedulerBinding.instance!.addPostFrameCallback((_) {
// Call your function
});
Using Future
class:
Future(() {
// Call your function
});
Using Timer
class:
Timer(() {
// Call your function
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With