Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

flutter

dart

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);
    }
   }
like image 539
Code Hunter Avatar asked May 31 '19 12:05

Code Hunter


5 Answers

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

like image 125
siega Avatar answered Oct 28 '22 19:10

siega


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

 }
like image 39
Emilio Brandon Flanagan Avatar answered Oct 28 '22 19:10

Emilio Brandon Flanagan


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();
    });
  }
like image 28
James Allen Avatar answered Oct 28 '22 20:10

James Allen


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 {

  }
like image 6
MJ Montes Avatar answered Oct 28 '22 21:10

MJ Montes


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
    });
    
like image 2
CopsOnRoad Avatar answered Oct 28 '22 19:10

CopsOnRoad