You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Provider状态模式启动Flutter加载页时遇构建异常求助

解决build过程中调用markNeedsBuild()的Flutter错误

问题根源

你在EvaluationsPage的initState中调用fetchEvaluations,该方法内直接修改ValueNotifier的value(设置为LoadingEvaluationState)。此时EvaluationsPage仍处于框架的build流程中,Provider的状态变更会触发依赖Widget的重建请求,违反了Flutter"禁止在build阶段触发新重建"的规则,从而抛出错误。

解决方案

方法1:延迟到当前build完成后执行状态更新

利用WidgetsBinding.instance.addPostFrameCallback,将状态更新操作推迟到当前帧构建完成后执行:

@override
void initState() {
  super.initState();
  WidgetsBinding.instance.addPostFrameCallback((_) {
    Provider.of<EvaluationStore>(context, listen: false).fetchEvaluations();
  });
}

方法2:通过微任务队列延迟执行

使用Future.microtask将请求放入微任务队列,确保在当前build周期结束后执行:

@override
void initState() {
  super.initState();
  Future.microtask(() {
    Provider.of<EvaluationStore>(context, listen: false).fetchEvaluations();
  });
}

方法3:初始化时默认设置Loading状态

直接在EvaluationStore的构造函数中设置初始状态为LoadingEvaluationState,避免在initState中触发状态变更:

class EvaluationStore extends ValueNotifier<EvaluationState> {
  EvaluationStore() : super(LoadingEvaluationState()); // 初始状态设为加载中

  Future<void> fetchEvaluations() async {
    try {
      final evaluations = await EvaluationService.getEvaluations();
      value = LoadedEvaluationState(evaluations);
    } catch (e) {
      value = ErrorEvaluationState(e.toString());
    }
  }
}

关键说明

移除value = LoadingEvaluationState()后应用正常,是因为此时fetchEvaluations仅在异步请求完成后才触发状态变更,而此时当前build周期已经结束,不会触发框架的重建冲突。

内容的提问来源于stack exchange,提问作者Galdino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 16:15:41