前言
我们在前面几篇中讨论了组合阶段生成的 Slot Table。但真正参与测量、排版和交给 Skia 绘制的“实体”是什么?
它就是 LayoutNode。今天我们来深度对比它与传统 View 的差异。
一、 LayoutNode vs View.java
作为一个十年老兵,你可能对 android.view.View 的 3 万行源码记忆犹新。LayoutNode 是 Compose 时代的对应物,但它实现了彻底的“功能剥离”。
| 特性 | View.java | LayoutNode |
|---|---|---|
| 职责 | 状态管理、触摸、绘制、测量、动画全包 | 仅负责几何结构(测量与位置) |
| 层级 | 必须继承 | 组合优于继承 |
| 状态持有 | 内部持有各种私有变量 | 状态存储在外部的 Slot Table 中 |
二、 LayoutNode 的生命周期
- 挂载 (Attached):由
Applier将其插入到节点树中。 - 测量 (Remeasured):当父约束变动或子项触发重绘。
- 布局 (Relayout):确定
offset。 - 绘制 (Redrawn):生成绘制指令流。
三、 核心链路:MeasurePolicy 的调度
LayoutNode 内部持有一个 MeasurePolicy。
- 当你调用
Modifier.layout时,其实是在为这个LayoutNode动态注入测量逻辑。 - 它严格遵守 “Parent-Child”单向约束协议。
四、 秘密武器:Owner 接口
LayoutNode 并不直接与 Android 系统打交道。它通过一个名为 Owner 的接口(在 Android 上的具体实现是 AndroidComposeView)与外界通信。
- Owner 的职责:
- 接收系统的点击事件,并分发给正确的
LayoutNode。 - 管理无效化(Invalidation)区域。
- 触发最终的 Canvas 绘制。
- 接收系统的点击事件,并分发给正确的
五、 给十年老兵的架构启示
- 节点轻量化:由于
LayoutNode比View轻得多,这解释了为什么我们可以肆无忌惮地使用Box、Column来美化代码结构,而不用担心对象创建开销。 - 树的操作是昂贵的:虽然
LayoutNode轻量,但频繁的树结构变动(如不恰当的if/else显隐切换)依然会导致 Slot Table 和节点树的大规模重构。
🏗️ 源码关键点
androidx.compose.ui.node.LayoutNodeandroidx.compose.ui.node.InnerNodeCoordinatorandroidx.compose.ui.platform.AndroidComposeView
结语
LayoutNode 是逻辑与像素之间的最后一道防线。它只管几何,不管逻辑,这种纯粹性赋予了 Compose 极速排版的能力。
下一篇,我们将进入图形学领域,研究 DrawScope 与 GraphicsLayer 的加速奥秘。