Flutter:在使用提供程序进行构建期间调用了setState()或markNeedsBuild()

时间:2020-03-18 06:59:10

标签: flutter flutter-provider

我正在从ChangeNotifier方法调用initState()函数之一,而函数内部的notifyListener()调用正在抛出 setState() or markNeedsBuild() called during build.例外

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

我需要在notifyListener()内调用setUnreadCount(),因为我在执行过程中在多个地方调用了setUnreadCount()函数。因此,不能仅在notifyListener()内部删除initState()

使用provider版本4.0.4

2 个答案:

答案 0 :(得分:0)

您可以将Provider.of<MessengerRepository>(context, listen: false).setUnreadCount(0);intState移到didChangeDependecies,然后只有页面完成构建过程时才会调用它。

或者通过这种方式:(不太优雅)

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

然后

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

initState中调用它时,如果build方法在所有变量都被(重新)分配之前完成,则直到您调用setStatenotifyListeners时它们才会更新

Learn more here

答案 1 :(得分:0)

日志消息中提到的这个问题的原因是 initState() 内部的函数正在通过 notifyListener() 请求重建(如果我们使用 setState() 也会发生同样的情况)甚至在第一个构建完成之前。

解决办法是添加一个addPostFrameCallback并在其中执行重建函数,这样它只会在第一次构建widget之后执行

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