上一篇简单的看了下Widget的源码,发现Widget主要作用就是createElement()。

贴出来Element系列的类关系图。

http://img.cdn.canhuah.com/image-20221129093402620.png

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
abstract class Element extends DiagnosticableTree implements BuildContext {

Element(Widget widget)
: assert(widget != null),
_widget = widget;

Element? _parent;

///Element中持有Widget,且是通过构造方法入参Widget。
Widget _widget;

bool _dirty = true;

///BuildOwner可以先粗看作是构建管理者,
//维护了 List<Element> _dirtyElements和Map<GlobalKey, Element> _globalKeyRegistry
BuildOwner**?** _owner**;

///** RenderObjectElement会持有renderObject
****RenderObject? get renderObject {
RenderObject? result;
void visit(Element element) {
assert(result == null); // this verifies that there's only one child
if (element is RenderObjectElement)
result = element.renderObject;
else
element.visitChildren(visit);
}
visit(this);
return result;
}
**...

}**

Element.mount和Element.unmount

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
Element.class
/// Add this element to the tree in the given slot of the given parent.
///挂载 默认实现 子类都有各自的扩充实现
void mount(Element? parent, Object? newSlot) {
///_parent,_slot,_lifecycleState,_owner赋值
_parent = parent;
_slot = newSlot;
_lifecycleState = _ElementLifecycle.active;
///计算了_depth
_depth = _parent != null ? _parent!.depth + 1 : 1;
if (parent != null) {
_owner = parent.owner;
}

final Key? key = widget.key;
if (key is GlobalKey) {
///给owner._globalKeyRegistry的map赋值,建立GlobalKey和Element的管理
///在unmount中有unRegister操作
owner!._registerGlobalKey(key, this);
}
_updateInheritance();
}

void unmount() {
final Key? key = _widget.key;
if (key is GlobalKey) {
/// 对应mount方法中的register
owner!._unregisterGlobalKey(key, this);
}
_lifecycleState = _ElementLifecycle.defunct;
}

Element的mount方法和unmount都比较简单。

mount方法将element插入到Element树上指定的位置。

但是Element的子类大都对mount方法进行了扩充,这个后面会具体分析。

1
2
3
4
5
6
7
8
9
10
ComponentElement.class

void mount(Element? parent, Object? newSlot) {
super.mount(parent, newSlot);
_firstBuild();
}

void _firstBuild() {
rebuild();
}
1
2
3
4
5
6
7
8
9
10
RenderObjectElement.class

RenderObjectWidget get widget => super.widget as RenderObjectWidget;

void mount(Element? parent, Object? newSlot) {
super.mount(parent, newSlot);
_renderObject = widget.createRenderObject(this);
attachRenderObject(newSlot);
_dirty = false;
}

Element.updateChild

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
Element? updateChild(Element? child, Widget? newWidget, Object? newSlot) {
if (newWidget == null) {
///移除旧的子元素
if (child != null) deactivateChild(child);
return null;
}
final Element newChild;
if (child != null) {
///非debug条件下这个值恒为true 后面条件可以忽略这个标志位
bool hasSameSuperclass = true;

if (hasSameSuperclass && child.widget == newWidget) {
///更新子元素的newSlot
if (child.slot != newSlot) updateSlotForChild(child, newSlot);
newChild = child;
} else if (hasSameSuperclass &&
Widget.canUpdate(child.widget, newWidget)) {
///能更新就更新slot 和 widget
if (child.slot != newSlot) updateSlotForChild(child, newSlot);
///调用子节点child的update方法
child.update(newWidget);
newChild = child;
} else {
deactivateChild(child);
assert(child._parent == null);
newChild = inflateWidget(newWidget, newSlot);
}
} else {
newChild = inflateWidget(newWidget, newSlot);
}
return newChild;
}

newWidget==null newWidget != null
child == null returns null. returns new [Element]
child != null 移除child,returns null 可复用就复用,returns child
不可复用,return new [Element]

各种条件下来其实就是 能更新就更新,否则移除旧的child,创建并返回新的Element。

Element.update

1
2
3
void update(covariant Widget newWidget) {
_widget = newWidget;
}

update方法很简单,实际上各个子类都对其进行了重写。

Element.inflateWidget

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Element inflateWidget(Widget newWidget, Object? newSlot) {
assert(newWidget != null);
final Key? key = newWidget.key;
if (key is GlobalKey) {
///GlobalKey的复用逻辑

///从InactiveElement中获取element
final Element? newChild = _retakeInactiveElement(key, newWidget);
if (newChild != null) {
///有可以复用的Element 更新子视图
newChild._activateWithParent(this, newSlot);
final Element? updatedChild = updateChild(newChild, newWidget, newSlot);

return updatedChild!;
}
}

///无法复用则创建新的Element
final Element newChild = newWidget.createElement();
newChild.mount(this, newSlot);
return newChild;
}

Element其他方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void didChangeDependencies() {
markNeedsBuild();
}

void markNeedsBuild() {
if (_lifecycleState != _ElementLifecycle.active) return;

if (dirty) return;
_dirty = true;
///
owner!.scheduleBuildFor(this);
}

void rebuild() {
if (_lifecycleState != _ElementLifecycle.active || !_dirty) return;

performRebuild();
}

///抽象,子类做了具体的实现
void performRebuild();

Element的主要源码到这就差不多结束了。其实整个看下来,除了在构造时入参了Widget,整个看下来和Widget的关联并不是很大。其实不然,还需要看看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
abstract class ComponentElement extends Element {

ComponentElement(Widget widget) : super(widget);

Element? _child;

@override
void mount(Element? parent, Object? newSlot) {
///先调用super.mount
super.mount(parent, newSlot);
///_firstBuild->rebuild->performRebuild
_firstBuild();
}

void _firstBuild() {
rebuild();
}

@override
void performRebuild() {

Widget? built;
try {

///调用build方法创建Widget
built = build();

} catch (e, stack) {

} finally {
_dirty = false;
}
try {

///更新子节点
_child = updateChild(_child, built, slot);

} catch (e, stack) {

_child = updateChild(null, built, slot);
}
}
@protected
Widget build();
}

组合型Element的mount方法经过_firstBuild->rebuild->performRebuild;最终会调用build方法创建Widget,然后调用updateChild方法更新子节点。

对于StatelessElement.build→StatelessWidget.build方法

对于StatefulElement.build→StatefulWidget.state.build方法

这里我们就知道了widget.build方法第一次调用是在Element.mount调用的时候被调用的。

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
class StatelessElement extends ComponentElement {
@override
Widget build() => widget.build(this);

@override
void update(StatelessWidget newWidget) {
super.update(newWidget);
_dirty = true;
rebuild();
}

}

class StatefulElement extends ComponentElement {
@override
Widget build() => state.build(this);

@override
void update(StatefulWidget newWidget) {
super.update(newWidget);
final StatefulWidget oldWidget = state._widget!;
_dirty = true;
state._widget = widget as StatefulWidget;
try {
final Object? debugCheckForReturnedFuture = state.didUpdateWidget(oldWidget) as dynamic;
} finally {
}
rebuild();
}


abstract class ProxyElement extends ComponentElement {
@override
Widget build() => widget.child;

@override
void update(ProxyWidget newWidget) {
final ProxyWidget oldWidget = widget;
super.update(newWidget);
updated(oldWidget);
_dirty = true;
rebuild();
}
}

StatelessElement,StatefulElement,ProxyElement的update→rebuild→performRebuild,会再次触发各自的build方法。

渲染型Element

渲染型的Element比较复杂,后面再补充