Flutter:在使用 Provider 构建期间调用 setState() 或 markNeedsBuild()

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

我正在从 initState() 方法调用 ChangeNotifier 函数之一,而函数内部的 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();
}

我需要在 setUnreadCount() 中调用 notifyListener(),因为我在执行期间在多个地方调用 setUnreadCount() 函数。所以不能只删除 initState().

里面的 notifyListener()

使用 provider 版本 4.0.4

您可以将 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 中调用它时,如果构建方法在所有变量被(重新)分配之前完成,它们将不会更新,直到您调用 setStatenotifyListeners

Learn more here

日志消息中提到的这个问题的原因是 initState() 中的函数正在请求通过 notifyListener() 重建(如果我们使用 setState() 作为好吧)甚至在第一次构建完成之前。

解决方法是加一个addPostFrameCallback,在里面执行rebuilding函数,这样只在第一次build widget后才执行

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