Flutter setState() or markNeedsBuild() called when widget tree was locked

As a workaround wrap your code that calling setState into WidgetsBinding.addPostFrameCallback:

WidgetsBinding.instance
        .addPostFrameCallback((_) => setState(() {}));

That way you can be sure it gets executed after the current widget is built.


This is not a thread problem. This error means that you are calling setState during the build phase.

A typical example would be the following :

Widget build(BuildContext context) {
    myParentWidgetState.setState(() { print("foo"); });
    return Container();
}

But the setState call may be less obvious. For example a Navigator.pop(context) does a setState internally. So the following :

Widget build(BuildContext context) {
    Navigator.pop(context);
    return Container();
}

is a no go either.


Looking at the stacktrace it seems that simultaneously with the Navigator.pop(context) your modal try to update with new data.


Special case of using Scaffold and Drawer:

That fail can also happen if you try to rebuild the tree with opened Drawer. For example if you send a message to a Bloc that forces rebuilding of the whole page/screen.

Consider to call Navigator.pop(context) first in your tap handler.