声明式 UI 架构下的生命周期演进:从内建属性到显式订阅
消失的“实体”: 从View到Composable/Widget
在原生Android开发的世界, 创建模版项目后就会得到一个MainActivity和activity_main.xml.
我们习惯了在MainActivity里去绑定Button和Text再设置各种属性. 他们都是内存中看得见,摸得着的View.
但是到了Flutter中, 得到的了却是main()函数和一堆StatelessWidget和StatefulWidget.
不仅仅是Flutter, 连Jetpack Compose也在向这种’声明式UI’靠拢.
Compose中同样找不到onResume(入口Activity除外),取而代之的而是层层嵌套的Composable函数
这种转变本质上是:我们不再持有 UI 的“句柄”,我们只持有“数据”。
正因为我们持有的只是数据,而数据本身是没有‘前后台’概念的(一个 String 字符串哪里知道自己是否在前台?)。所以,在声明式 UI 中寻找 onResume 本身就是一个伪命题。
只有当数据需要根据系统状态(如用户回来了)进行刷新时,我们才去主动询问系统。
为什么 onResume 不再属于 UI 组件
View体系的“重形约束”
在原生 Android 中,Activity 是一个重型容器,它直接占据着系统的窗口资源和输入焦点。这种设计决定了开发者必须拥有极强的“生存意识”:
- 前后台切换: 我们必须精确掌握 onPause 和 onResume,以便在失去焦点时停止动画或暂停视频。
- 极限生存: 在电池优化策略或“不保留活动”的极限测试下,Activity 随时会被销毁,我们不得不依赖 onSaveInstanceState 艰难地维持状态。
- 任务流转: 耗时后台任务必须挪到专门的 Foreground/Background Service 中,否则随时会被系统“祭天”。
声明式 UI 的“逻辑重构”
但在 Flutter 和 Compose 的世界里,这种“资源焦虑”被屏蔽了。我们面对的是轻量级的函数和配置。
- UI 即快照: 界面不再是长存的实体,而是数据的瞬时表达。销毁一个 Widget 就像扔掉一张草稿纸,成本极低。
- 底层重构: 这种变化不仅仅是语法上的,更是底层生存逻辑的重构。你不再需要盯着每一个 View 对象的死活,只需要守护好背后的 State。
消失的本质:为什么它们敢“干掉” onResume?
在原生 Android 中,View 是一个具有稳定身份(Stable Identity)的对象。你通过 findViewById 拿到的 Button,在它被销毁前,其内存地址是不变的,因此它可以安全地持有状态与生命周期回调。
而在 Flutter 中,Widget 仅是不可变的配置描述(Immutable Configuration)。 它在每一帧都可能被重新创建。 你无法给一个“瞬时快照”绑定生命周期,因为这个对象本身随时会消失。 真正具有生命周期的不是 Widget,而是底层的 State 对象,因为它在 Widget 重建时依然保持稳定。
只有当业务需要时,才去“订阅”环境
其实 Flutter 并非没有生命周期,只是它不再作为 UI 组件的内建能力。 我们需要区分三个维度的生命周期:
- App 级别(WidgetsBinding):整个应用进程的前后台信号。
- 页面级别(RouteAware):当前页面是否处于导航栈顶的可见状态。
- 组件级别(Composition):Widget 进入或退出 UI 树的过程。
将这些信号与 UI 描述彻底解耦,正是 Flutter 极致灵活的原因。
Flutter 方案:监听 AppLifecycleState
在 Flutter 中,需要通过 WidgetsBindingObserver 来扮演那个“哨兵”的角色。
WidgetsBindingObserver 的订阅是 State 级别的,而不是 Widget 级别的。
1 | // 建议替换原本的 Flutter 代码块 |
Compose 方案:通过副作用显式接入宿主生命周期
Compose 并没有“移除” onResume,而是拒绝让 UI 组件隐式地持有它。
1 |
|
结语:从“被动接受”到“主动订阅”
从原生 Android 转向 Flutter 或 Compose,最难的不是学习新的语法,而是思维权力的移交。
在传统的 View 体系中,生命周期是系统强行塞给我们的“全家桶”,我们作为开发者,更多是在被动地接受 Activity 的调度。而声明式 UI 的出现,将组件彻底从繁重的系统环境依赖中解放出来。
这种“消亡”实际上是一种进化:
它让我们更关注数据本身:UI 不再是长存的“房子”,而是随数据流动的“快照”。
它赋予了我们订阅的自由:不再为了那 1% 的业务需求让 100% 的组件去负担生命周期回调,而是根据业务逻辑,在需要的地方精准地拉出一根“信号线”。
生命周期没有消失,只是从“隐式回调”进化为了“显式订阅”。
声明式 UI 架构下的生命周期演进:从内建属性到显式订阅
https://chaosgoo.com/2024/01/02/the-death-of-onresume-declarative-ui-lifecycle/


