Flutter Widget/Element/RenderObject 三树关系深度解析

源码路径:packages/flutter/lib/src/widgets/framework.dart

一、三树模型概述

Flutter 的核心架构基于三棵树:

  • Widget Tree:配置层,不可变、轻量,描述”应该是什么样子”
  • Element Tree:状态层,可变、持久,管理 Widget 和 RenderObject 的对应关系
  • RenderObject Tree:渲染层,负责布局、绘制和命中测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
flowchart LR
subgraph "Widget Tree 配置"
W1["StatelessWidget"] --> W2["Container"]
W1 --> W3["Text"]
end
subgraph "Element Tree 状态"
E1["StatelessElement"] --> E2["SingleChildRenderObjectElement"]
E1 --> E3["LeafRenderObjectElement"]
end
subgraph "RenderObject Tree 渲染"
R1["RenderPadding"] --> R2["RenderParagraph"]
end

W1 -.->|createElement| E1
W2 -.->|createElement| E2
W3 -.->|createElement| E3
E2 -.->|renderObject| R1
E3 -.->|renderObject| R2

二、Widget 核心类层次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
classDiagram
class Widget {
<<abstract>>
+key : Key?
+createElement() Element
+canUpdate(old, new) bool static
}
class StatelessWidget {
+build(context) Widget
+createElement() StatelessElement
}
class StatefulWidget {
+createState() State
+createElement() StatefulElement
}
class ProxyWidget {
+child : Widget
}
class RenderObjectWidget {
+createRenderObject() RenderObject
+updateRenderObject()
+didUnmountRenderObject()
+createElement() RenderObjectElement
}
class LeafRenderObjectWidget {
+createElement() LeafRenderObjectElement
}
class SingleChildRenderObjectWidget {
+child : Widget?
+createElement() SingleChildRenderObjectElement
}
class MultiChildRenderObjectWidget {
+children : List~Widget~
+createElement() MultiChildRenderObjectElement
}

Widget <|-- StatelessWidget
Widget <|-- StatefulWidget
Widget <|-- ProxyWidget
Widget <|-- RenderObjectWidget
RenderObjectWidget <|-- LeafRenderObjectWidget
RenderObjectWidget <|-- SingleChildRenderObjectWidget
RenderObjectWidget <|-- MultiChildRenderObjectWidget
ProxyWidget <|-- InheritedWidget
ProxyWidget <|-- ParentDataWidget

Widget.canUpdate — Diff 算法核心

1
2
3
4
5
// L432: 决定是否可复用旧 Element
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}

canUpdate 返回 true → 复用旧 Element,调用 element.update(newWidget)
canUpdate 返回 false → 旧 Element 卸载,创建新 Element


三、Element 核心类层次与生命周期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
classDiagram
class Element {
<<abstract>>
+widget : Widget
+depth : int
+owner : BuildOwner
+slot : dynamic
+mount(parent, slot)
+update(newWidget)
+deactivate()
+unmount()
+findAncestorRenderObjectElement()
}
class ComponentElement {
+_child : Element?
+performRebuild()
+mount() rebuild
}
class StatelessElement {
+build() widget.build(this)
}
class StatefulElement {
+_state : State
+build() state.build(this)
+mount() state.initState()
+update() state.didUpdateWidget()
+deactivate() state.deactivate()
+unmount() state.dispose()
}
class RenderObjectElement {
+renderObject : RenderObject
+mount() createRenderObject + attachRenderObject
+update() updateRenderObject
+deactivate() detachRenderObject
+unmount() didUnmountRenderObject
}
class LeafRenderObjectElement
class SingleChildRenderObjectElement
class MultiChildRenderObjectElement

Element <|-- ComponentElement
Element <|-- RenderObjectElement
ComponentElement <|-- StatelessElement
ComponentElement <|-- StatefulElement
RenderObjectElement <|-- LeafRenderObjectElement
RenderObjectElement <|-- SingleChildRenderObjectElement
RenderObjectElement <|-- MultiChildRenderObjectElement

Element 生命周期状态机

1
2
3
4
5
6
7
8
stateDiagram-v2
[*] --> initial : createElement()
initial --> active : mount(parent, slot)
active --> active : update(newWidget)
active --> inactive : deactivate()
inactive --> active : activate() GlobalKey复用
inactive --> defunct : unmount()
defunct --> [*]

四、updateChild — 三树更新的核心调度

updateChild 是 Element 更新子节点的核心方法,根据 Widget.canUpdate 的结果决定子 Element 的命运:

1
2
3
4
5
6
7
8
9
10
11
12
13
flowchart TD
A["updateChild(child, newWidget, newSlot)"] --> B{"newWidget == null?"}
B -->|是| C{"child != null?"}
C -->|是| D["deactivateChild(child)<br/>子树卸载"]
C -->|否| E["return null 无操作"]
B -->|否| F{"child != null?"}
F -->|是| G{"Widget.canUpdate?<br/>runtimeType+key 相同?"}
G -->|是| H["child.update(newWidget)<br/>复用 Element"]
G -->|否| I["newChild = inflateWidget<br/>deactivateChild(old)"]
F -->|否| J["newChild = inflateWidget<br/>创建新 Element"]
H --> K["return child"]
I --> K
J --> K

核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// L3982: updateChild — 子 Element 更新调度
Element? updateChild(Element? child, Widget? newWidget, dynamic newSlot) {
if (newWidget == null) {
if (child != null) deactivateChild(child);
return null;
}
if (child != null) {
if (Widget.canUpdate(child.widget, newWidget)) {
child.update(newWidget); // 复用
return child;
}
deactivateChild(child); // 卸载旧
}
return inflateWidget(newWidget, newSlot); // 创建新
}

五、Element.mount 挂载流程

1
2
3
4
5
6
flowchart TD
A["mount(parent, newSlot)"] --> A1["_parent = parent"]
A1 --> A2["_slot = newSlot"]
A2 --> A3["depth = parent.depth + 1"]
A3 --> A4["_owner = parent.owner"]
A4 --> A5["parent.updateChild(this, widget, slot)"]

ComponentElement.mount

1
2
3
4
flowchart TD
B1["super.mount()"] --> B2["rebuild() → performRebuild()"]
B2 --> B3["StatelessElement: widget.build(this)"]
B2 --> B4["StatefulElement: state.initState() → state.build()"]

RenderObjectElement.mount

1
2
3
4
flowchart TD
C1["super.mount()"] --> C2["_renderObject = widget.createRenderObject()"]
C2 --> C3["attachRenderObject(newSlot)"]
C3 --> C4["renderObject.attach(owner)"]

六、RenderObjectElement 与 RenderObject 的桥接

1
2
3
4
5
6
7
8
9
10
11
12
flowchart TD
A["RenderObjectElement.mount()"] --> B["widget.createRenderObject(this)"]
B --> C["renderObject = 新 RenderObject"]
C --> D["attachRenderObject(newSlot)"]
D --> E["renderObject.attach(owner.pipelineOwner)"]

F["RenderObjectElement.update(newWidget)"] --> G["super.update()"]
G --> H["widget.updateRenderObject(this, renderObject)"]

I["RenderObjectElement.unmount()"] --> J["widget.didUnmountRenderObject(renderObject)"]
J --> K["renderObject.detach()"]
K --> L["owner.releaseRenderObject(renderObject)"]

七、BuildOwner 构建管理

1
2
3
4
5
6
7
8
9
flowchart TD
A["BuildOwner"] --> B["_dirtyElements : List~Element~"]
A --> C["_globalKeyRegistry : Map~Key, Element~"]

D["onBuildScheduled()"] --> E["ensureVisualUpdate()"]
F["buildScope(context, callback)"] --> G["排序 _dirtyElements depth升序"]
G --> H["遍历 dirty Elements"]
H --> I["element.rebuild() → performRebuild()"]
I --> J["finalizeTree() → unmount 不可恢复的 Elements"]

八、完整帧构建流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
flowchart TD
A["BuildOwner.buildScope()"] --> B["按 depth 升序排序 dirty Elements"]
B --> C["遍历每个 dirty Element"]
C --> D["element.rebuild()"]
D --> E["ComponentElement.performRebuild()"]
E --> F["built = build()"]
F --> G["updateChild(_child, built, slot)"]
G --> H{"Widget.canUpdate?"}
H -->|复用| I["child.update(newWidget)"]
H -->|新建| J["inflateWidget → createElement → mount"]
H -->|卸载| K["deactivateChild → deactivate → unmount"]
J --> L["RenderObjectElement.mount"]
L --> M["createRenderObject → attachRenderObject"]
I --> N["RenderObjectElement.update"]
N --> O["updateRenderObject → markNeedsLayout/markNeedsPaint"]

九、StatefulElement 与 State 的交互

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
flowchart TD
A["StatefulElement.mount()"] --> A1["super.mount()"]
A1 --> A2["_state = widget.createState()"]
A2 --> A3["_state._element = this"]
A3 --> A4["_state.initState()"]
A4 --> A5["rebuild() → _state.build()"]

B["StatefulElement.update(newWidget)"] --> B1["_state.didUpdateWidget(oldWidget)"]
B1 --> B2["rebuild() → _state.build()"]

C["setState(callback)"] --> C1["_element.markNeedsBuild()"]
C1 --> C2["BuildOwner.scheduleBuildFor(_element)"]
C2 --> C3["下一帧 buildScope → rebuild"]

D["StatefulElement.deactivate()"] --> D1["_state.deactivate()"]
E["StatefulElement.unmount()"] --> E1["_state.dispose()"]

十、关键调用链总结

场景 调用链
首次构建 mount()rebuild()build()updateChild(null, built, slot)inflateWidget()createElement()child.mount()
Widget 更新 markNeedsBuild()buildScope()rebuild()build()updateChild(old, built, slot)canUpdate? update/inflate
Widget 替换 canUpdate = falsedeactivateChild()inflateWidget() → 旧 Element deactivate → 新 Element mount
State 更新 setState()markNeedsBuild() → 下一帧 rebuild()build()
Element 卸载 deactivate() → 移入 _inactiveElementsunmount()RenderObjectElement.unmount()detachRenderObject()
GlobalKey 复用 inflateWidget()globalKeyRegistry 查找 → 旧 Element deactivate → activate() 复用