Unhandled Exception: inheritFromWidgetOfExactType(_LocalizationsScope) or inheritFromElement() was called before _ScreenState.initState() completed

大憨熊 提交于 2021-01-21 06:20:25

问题


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);
    }
   }

回答1:


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 like showed in another answers.




回答2:


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
  // ...

 }



回答3:


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();
    });
  }



回答4:


an alternative is to put it inside PostFrameCallback which is between initState and Build so we can be sure that the initState is already finished.

 @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((_) => getData());
    super.initState();
  }

  getData() async {

  }



回答5:


The best solution i think is use the context from the Widget build. And paste the method _getCategories(context) after the build with the context from the tree. So there is no problem with the widget tree.




回答6:


Use after_init package to handle this issue

Adds a didInitState() lifecycle method to stateful widgets where you can safely access inherited widgets.

InheritedWidget is heavily used throughout the Flutter framework. Many state management packages such as ScopedModel and Provider use it as well. Unfortunately, InheritedWidgets are not accessible from the initState() method of State.

Example:

import 'package:flutter/material.dart';
import 'package:after_init/after_init.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        body: Example(),
      ),
    ),
  );
}

class Example extends StatefulWidget {
  @override
  _ExampleState createState() => _ExampleState();
}

class _ExampleState extends State<Example> with AfterInitMixin<Example> {
  Size size;

  /// This gets called first, as usual.
  @override
  void initState() {
    super.initState();
    // Your code here
  }

  /// This gets called after initState(), only once.
  /// Safely access inherited widgets here.
  @override
  void didInitState() {
    // No need to call super.didInitState().
    // setState() is not required because build() will automatically be called by Flutter.
    size = MediaQuery.of(context).size;
  }

  /// This gets called after didInitState().
  /// And anytime the widget's dependencies change, as usual.
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // Your code here
  }

  /// Finally this gets called, as usual.
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(size.toString()),
    );
  }
}


来源:https://stackoverflow.com/questions/56395081/unhandled-exception-inheritfromwidgetofexacttype-localizationsscope-or-inheri

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!