这是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框架构建流程的开发者,写出业务逻辑错误的代码

之所以不能继承 initState,是因为我们以前允许这样做,而用户会直接在 initState 中查找继承的值,却没有设置 didChangeDependencies 来处理继承值发生变化的情况。现在必须使用 didChangeDependencies,这样就很难出错了。
同样的问题似乎不适用于非继承的情况,因为非继承的关键在于你不会查找并依赖它(例如,继承了一个带有日志记录器的组件,以便发送一条日志消息,但如果日志记录器之后发生变化,你就无法获取到这条消息)。
简单来说,initstate在一个state的生命周期里只会被调用一次
而didChangeDependencies会在祖先组件InheritedWidget发生更改时被调用
(例如由白天模式切换成黑夜模式,配色方案会发生改变时被调用(stless/stful在第一次通过context向上查找祖先组件时会注册)
如果开发者不小心只在initstate获取到了值的话可能会无法响应祖先组件的更新…
算是一个”框架为业务逻辑做兜底”的一个规定吧,学习过程中可以不用太钻牛角尖的
评论(0)
暂无评论