Flutter中使用FutureBuilder触发build阶段更新异常的问题咨询
问题分析与解决方案
错误根源
你的问题核心出在DoctorsProvider.getDoctors()的同步触发逻辑上:
- 虽然方法标记了
async,但内部给_doctors赋值Mock数据后,立刻同步调用了notifyListeners()。当你在initState或组件build阶段执行这个Future时,组件正处于构建流程中,此时触发状态通知会导致框架抛出「setState() or markNeedsBuild() called during build.」异常。 - 另外,你最初的Stateless组件写法有隐性问题:直接把
_refreshDoctors(context)传给FutureBuilder的future参数,会导致每次组件构建都重新创建Future,触发FutureBuilder反复重建——不过转成Stateful后这个问题已经解决,但同步通知的bug依然存在。
修复方案
方案1:延迟状态通知到构建完成后
修改DoctorsProvider的getDoctors方法,用Future.microtask把状态通知延迟到当前构建周期结束后执行:
Future<void> getDoctors() async { _doctors = MockedDoctorsProvider().doctors; // 延迟触发通知,避开组件构建阶段 await Future.microtask(() => notifyListeners()); }
方案2:模拟真实异步请求逻辑
如果是模拟接口请求,给Mock数据的获取添加异步延迟,让Future真正进入异步队列执行:
Future<void> getDoctors() async { // 哪怕是0时长延迟,也能让Future脱离同步构建流程 await Future.delayed(const Duration(milliseconds: 0)); _doctors = MockedDoctorsProvider().doctors; notifyListeners(); }
额外说明
你当前的Stateful组件写法是正确的(把Future存在成员变量里,避免每次构建重建Future),保持即可。另外不存在无限循环:Consumer只会在notifyListeners()触发时重建对应部分,只要不在Consumer的builder回调里调用getDoctors(),就不会出现循环重建的问题。
内容的提问来源于stack exchange,提问作者Ficusstrangler
相关产品推荐
相关产品推荐

