boxmoe_header_banner_img

Hello! 欢迎来到哭哭痛!

文章导读

关于initstate()和didChangeDependencies()


avatar
哭哭痛 26 5 月, 2026 22

这是element在将自己挂载到上下文树的element.mount(Element? parent, Object? newSlot)方法:

@override
void mount(Element? parent, Object? newSlot) {
  super.mount(parent, newSlot);
  
  // 1. 创建 State 对象
  _state = widget.createState();
  _state._element = this;
  _state._widget = widget;
  
  // 2. 初始化状态 (状态锁:_debugLifecycleState = _StateLifecycle.created)
  _debugLifecycleState = _StateLifecycle.created;
  _state.initState();
  
  // 3. 准备依赖初始化通道 (状态锁:_debugLifecycleState = _StateLifecycle.initialized)
  _debugLifecycleState = _StateLifecycle.initialized;
  _state.didChangeDependencies();
  
  // 4. 正式开始构建
  _firstBuild();
}

可以看到有创建state,state和element的双向绑定,以及设置状态锁initstate/didChangeDependencies

Flutter框架有个规定:向 祖先组件InheritedWidget 查询相关字段时,例如 Theme.of(context) 这种依赖 上下文context 向上查找 InheritedWidget订阅依赖 的方法 是不允许initstate里写的

你跑去问AI得到的答案大概是”依赖图谱注册表脏乱与拓扑遍历死锁””此时还在节点的mount阶段,子树未生成不允许向父类注册”……

但是在didChangeDependencies里又可以执行相关方法…这就很矛盾了

真相其实是flutter开发人员觉得,这会使不太了解flutter框架构建流程的开发者,写出业务逻辑错误的代码

Github原文:dependOnInheritedWidgetOfExactType should throw if used inside didUpdateWidget · Issue #49795 · flutter/flutter

之所以不能继承 initState,是因为我们以前允许这样做,而用户会直接在 initState 中查找继承的值,却没有设置 didChangeDependencies 来处理继承值发生变化的情况。现在必须使用 didChangeDependencies,这样就很难出错了。

同样的问题似乎不适用于非继承的情况,因为非继承的关键在于你不会查找并依赖它(例如,继承了一个带有日志记录器的组件,以便发送一条日志消息,但如果日志记录器之后发生变化,你就无法获取到这条消息)。

简单来说,initstate在一个state的生命周期里只会被调用一次

didChangeDependencies会在祖先组件InheritedWidget发生更改时被调用

(例如由白天模式切换成黑夜模式,配色方案会发生改变时被调用(stless/stful在第一次通过context向上查找祖先组件时会注册)

如果开发者不小心只在initstate获取到了值的话可能会无法响应祖先组件的更新…

算是一个”框架为业务逻辑做兜底”的一个规定吧,学习过程中可以不用太钻牛角尖的



评论(0)

查看评论列表

暂无评论


发表评论

表情 颜文字
插入代码