krishnakumarcn
krishnakumarcn

Reputation: 4199

Flutter: setState() or markNeedsBuild() called during build with Provider

I'm calling one of the ChangeNotifier functions from an initState() method and the notifyListener() call inside the function is throwing setState() or markNeedsBuild() called during build. exception

void initState(){
 Provider.of<MessengerRepository>(context, listen: false).setUnreadCount(0);
 super.initState();
}
class MessengerRepository with ChangeNotifier {
  int unreadCount;
  void setUnreadCount(int value){
     unreadCount = value;
     notifyListeners();
}

I need to call the notifyListener() inside setUnreadCount() as I'm calling the setUnreadCount() function in multiple places during the execution. So can't remove the notifyListener() only inside initState().

Using provider version 4.0.4

Upvotes: 3

Views: 4201

Answers (2)

krishnakumarcn
krishnakumarcn

Reputation: 4199

The cause for this issue as mentioned in the log message is that the function inside initState() is requesting a rebuild through notifyListener() (the same will happen if we use setState() as well) even before the first build is completed.

The solution is to add a addPostFrameCallback and execute the rebuilding function inside it so that it will execute only after the first building of the widget

void initState() {
    super.initState();
    WidgetsBinding
     .instance
     .addPostFrameCallback((_){ 
      Provider.of<MessengerRepository>(context, listen: false).setUnreadCount(0);
     }
    );
  }

Upvotes: 7

Constantin N.
Constantin N.

Reputation: 2839

You can move Provider.of<MessengerRepository>(context, listen: false).setUnreadCount(0); from intStateto didChangeDependecies then it'll be called only once page finishes build process.

Or by this way :(less elegant)

void setUnreadCount(int value, {bool shouldUpdate: true}){
     unreadCount = value;
   if(shouldUpdate)  notifyListeners();

Then

void initState(){
 Provider.of<MessengerRepository>(context, listen: false).setUnreadCount(0, shouldUpdate:false);
 super.initState();
}

When you call it in initState, if the build method finishes before all your variables are (re)assigned they'll not be updated until you call setState or notifyListeners

Learn more here

Upvotes: 0

Related Questions