0%

iOS Flutter Main runApp

1. 概述

使用下面 demo 来探究 main 函数干了啥。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void main() {
// 见 [2.1]
runApp(
materialApp(),
);
}

class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
Widget build(BuildContext context) {
return Container();
/*
// 因为 MaterialApp 里面的逻辑比较多,所以直接上 Container.
return MaterialApp(home: Container(),);
*/
}
}

2. 启动流程

调试堆栈如下

-w1247

2.1 runApp

1
2
3
4
5
6
// scr/widgets/binding.dart
void runApp(Widget app) {
WidgetsFlutterBinding.ensureInitialized() // 见 [2.2]
..scheduleAttachRootWidget(app) // 见 [2.4]
..scheduleWarmUpFrame(); // 见 [2.10]
}

2.2 ensureInitialized

1
2
3
4
5
6
7
8
9
10
11
// scr/widgets/binding.dart
/// A concrete binding for applications based on the Widgets framework.
///
/// This is the glue that binds the framework to the Flutter engine.
class WidgetsFlutterBinding extends BindingBase with GestureBinding, SchedulerBinding, ServicesBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
static WidgetsBinding ensureInitialized() {
if (WidgetsBinding.instance == null)
WidgetsFlutterBinding(); // 见 [2.2.1]
return WidgetsBinding.instance;
}
}

2.2.1 BindingBase 初始化

1
2
3
4
5
6
7
8
BindingBase() {
// 见 [2.3]
initInstances();
// ...

initServiceExtensions();
// ...
}

2.3 initInstances

initInstances 方法的调用顺序是从右到左的,即

  1. WidgetsBinding: The glue between the widgets layer and the Flutter engine.
  2. RendererBinding: The glue between the render tree and the Flutter engine.
  3. SemanticsBinding: The glue between the semantics layer and the Flutter engine.
  4. PaintingBinding: Binding for the painting library.
  5. ServicesBinding: Listens for platform messages and directs them to the [defaultBinaryMessenger].
  6. SchedulerBinding: Scheduler for running the following: xxx.
  7. GestureBinding: A binding for the gesture subsystem.

按照上面的顺序执行完 initInstances 中的 super.initInstances(), 再按照上面的逆序执行各个 BindinginitInstances 中剩余逻辑,然后执行 initServiceExtensions

2.3.1 GestureBinding

1
2
3
4
5
6
7
// scr/gestures/binding.dart
void initInstances() {
super.initInstances();
_instance = this;
// 设置 window 的 `onPointerDataPacket` 回调方法,在该回调方法中处理手势等交互逻辑。
window.onPointerDataPacket = _handlePointerDataPacket;
}

2.3.2 SchedulerBinding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// scr/scheduler/binding.dart
void initInstances() {
super.initInstances();
_instance = this;

// 非 `kReleaseMode` 模式下,添加 `addTimingsCallback` 回调,用来记录 frame 等相关信息。
if (!kReleaseMode) {
int frameNumber = 0;
addTimingsCallback((List<FrameTiming> timings) {
for (final FrameTiming frameTiming in timings) {
frameNumber += 1;
_profileFramePostEvent(frameNumber, frameTiming);
}
});
}
}

2.3.3 ServicesBinding

1
2
3
4
5
6
7
8
9
10
11
12
// scr/services/binding.dart
void initInstances() {
super.initInstances();
_instance = this;
_defaultBinaryMessenger = createBinaryMessenger();
_restorationManager = createRestorationManager();
window.onPlatformMessage = defaultBinaryMessenger.handlePlatformMessage;
initLicenses();
SystemChannels.system.setMessageHandler((dynamic message) => handleSystemMessage(message as Object));
SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage);
readInitialLifecycleStateFromNativeWindow();
}

创建 _defaultBinaryMessenger,用来处理 platform channel 消息,iOS Flutter Platform Channel 有讲到。

2.3.4 PaintingBinding

1
2
3
4
5
6
7
8
// scr/painting/binding.dart
void initInstances() {
super.initInstances();
_instance = this;
// 创建 image chache.
_imageCache = createImageCache();
shaderWarmUp?.execute();
}

2.3.5 SemanticsBinding

1
2
3
4
5
6
7
// scr/semantics/binding.dart
void initInstances() {
super.initInstances();
_instance = this;
// 给 _accessibilityFeatures 赋值
_accessibilityFeatures = window.accessibilityFeatures;
}

2.3.6 RendererBinding

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
// scr/rendering/binding.dart
void initInstances() {
super.initInstances();
_instance = this;
// 见 [2.3.6.1]
_pipelineOwner = PipelineOwner(
onNeedVisualUpdate: ensureVisualUpdate,
onSemanticsOwnerCreated: _handleSemanticsOwnerCreated,
onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed,
);
// 设置 window 的相关回调
window
..onMetricsChanged = handleMetricsChanged
..onTextScaleFactorChanged = handleTextScaleFactorChanged
..onPlatformBrightnessChanged = handlePlatformBrightnessChanged
..onSemanticsEnabledChanged = _handleSemanticsEnabledChanged
..onSemanticsAction = _handleSemanticsAction;
// 见 [2.3.6.2]
initRenderView();
_handleSemanticsEnabledChanged();
assert(renderView != null);
// 添加 addPersistentFrameCallback 回调
addPersistentFrameCallback(_handlePersistentFrameCallback);
initMouseTracker();
}

2.3.6.1 PipelineOwner 初始化

1
2
3
4
5
6
7
8
// The pipeline owner manages the rendering pipeline.
class PipelineOwner {
PipelineOwner({
this.onNeedVisualUpdate,
this.onSemanticsOwnerCreated,
this.onSemanticsOwnerDisposed,
});
}

用来管理 rendering pipeline 的类,在 rendering pipeline 过程中,会按序执行以下方法(这几个阶段的操作对象都是 render objects)

  1. flushLayout
  2. flushCompositingBits
  3. flushPaint
  4. flushSemantics

2.3.6.2 initRenderView

1
2
3
4
5
6
7
8
9
10
11
void initRenderView() {
assert(!_debugIsRenderViewInitialized);
assert(() {
_debugIsRenderViewInitialized = true;
return true;
}());
// 创建 RenderView 对象,并赋值给 renderView, 见 [2.3.6.3]
renderView = RenderView(configuration: createViewConfiguration(), window: window);
// 准备首帧
renderView.prepareInitialFrame();
}

2.3.6.3 set renderView

1
2
3
4
5
6
7
8
// The root of the render tree.
class RenderView extends RenderObject with RenderObjectWithChildMixin<RenderBox> {
set renderView(RenderView value) {
assert(value != null);
// 见 [2.3.6.4]
_pipelineOwner.rootNode = value;
}
}

2.3.6.4 set rootNode

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
class PipelineOwner {
set rootNode(AbstractNode? value) {
if (_rootNode == value)
return;
_rootNode?.detach();
_rootNode = value;
_rootNode?.attach(this);
}
}

class AbstractNode {
@mustCallSuper
void detach() {
assert(_owner != null);
_owner = null;
assert(parent == null || attached == parent!.attached);
}

@mustCallSuper
void attach(covariant Object owner) {
assert(owner != null);
assert(_owner == null);
_owner = owner;
}
}

_owner 和 _rootNode 的赋值。

  • 将 RenderView 对象赋值给 _pipelineOwner 的 rootNode 成员变量
  • 将 _pipelineOwner 赋值给 RenderView 对象的 _owner 成员变量

2.3.7 WidgetsBinding

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// scr/widgets/binding.dart
void initInstances() {
super.initInstances();
_instance = this;
// Initialization of [_buildOwner] has to be done after
// [super.initInstances] is called, as it requires [ServicesBinding] to
// properly setup the [defaultBinaryMessenger] instance.
_buildOwner = BuildOwner(); // 见 [2.3.7.1]
buildOwner.onBuildScheduled = _handleBuildScheduled;
window.onLocaleChanged = handleLocaleChanged;
window.onAccessibilityFeaturesChanged = handleAccessibilityFeaturesChanged;
SystemChannels.navigation.setMethodCallHandler(_handleNavigationInvocation);
FlutterErrorDetails.propertiesTransformers.add(transformDebugCreator);
}

2.3.7.1 BuildOwner 初始化

1
2
3
4
5
// scr/widgets/framework.dart
/// Manager class for the widgets framework.
class BuildOwner {
BuildOwner({ this.onBuildScheduled });
}

2.4 scheduleAttachRootWidget

1
2
3
4
5
6
7
void scheduleAttachRootWidget(Widget rootWidget) {
// 异步执行
Timer.run(() {
// 见 [2.4.1]
attachRootWidget(rootWidget);
});
}

2.4.1 attachRootWidget

1
2
3
4
5
6
7
8
9
void attachRootWidget(Widget rootWidget) {
_readyToProduceFrames = true;
// 见 [2.4.2]
_renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
container: renderView,
debugShortDescription: '[root]', // debug 描述信息
child: rootWidget,
).attachToRenderTree(buildOwner, renderViewElement as RenderObjectToWidgetElement<RenderBox>); // 见 [2.5]
}

该方法的主要参数

  • renderView: 见 [2.3.6.2]
  • rootWidget: 见 [1] 中的 demo, materialApp widget, 就是我们的 root widget
  • buildOwner: 见 [2.3.7.1]
  • _renderViewElement: 执行 attachToRenderTree 方法后,返回的 Element 类型的对象,可通过 WidgetsBinding.renderViewElement 获取,是 Element tree 的根节点(通过注释 The [Element] that is at the root of the hierarchy (and which wraps the [RenderView] object at the root of the rendering hierarchy).)。

2.4.2 RenderObjectToWidgetAdapter 初始化

1
2
3
4
5
6
7
8
// A bridge from a [RenderObject] to an [Element] tree.
class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWidget {
RenderObjectToWidgetAdapter({
this.child, // widget tree 中的对象
this.container, // The [RenderObject] that is the parent of the [Element] created by this widget.
this.debugShortDescription,
}) : super(key: GlobalObjectKey(container));
}

RenderObjectToWidgetAdapter 是一个从 [RenderObject](root of render tree) 到 [Element](root of element tree) 的桥接类,该类的主要方法有

  • createElement: 返回 RenderObjectToWidgetElement 对象, 见 [2.5.1]
  • createRenderObject: 返回 [2.3.6.2] 的 renderView, 见 [2.7]
  • attachToRenderTree: 创建 element, 见 [2.5]

2.5 attachToRenderTree

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement<T> element ]) {
if (element == null) {
owner.lockState(() {
// 见 [2.5.1]
element = createElement();
assert(element != null);
// 见 [2.5.2]
element.assignOwner(owner);
});
// 见 [2.5.3]
owner.buildScope(element, () {
// 见 [2.5.4]
element.mount(null, null);
});
SchedulerBinding.instance.ensureVisualUpdate();
} else {
element._newWidget = this;
element.markNeedsBuild();
}
return element;
}

首次调用 attachToRenderTree 方法时,入参 element 为空,会创建 element 对象(RenderObjectToWidgetElement 类型),然后赋值给 [2.4.1] 的 _renderViewElement 成员变量。

2.5.1 createElement

1
2
3
4
5
6
7
RenderObjectToWidgetAdapter({
this.child,
this.container,
this.debugShortDescription,
}) : super(key: GlobalObjectKey(container));

RenderObjectToWidgetElement<T> createElement() => RenderObjectToWidgetElement<T>(this);

返回 RenderObjectToWidgetElement 类型的对象。

2.5.2 assignOwner

1
2
3
4
5
6
// The element at the root of the tree.
abstract class RootRenderObjectElement extends RenderObjectElement {
void assignOwner(BuildOwner owner) {
_owner = owner;
}
}

跟 [2.3.6.4] 类似,都是将 _pipelineOwner 赋值给 _owner 成员变量,_pipelineOwner 不亏是一个管理类。

2.5.3 buildScope

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
void buildScope(Element context, [ VoidCallback callback ]) {
if (callback == null && _dirtyElements.isEmpty)
return;
// ...
Timeline.startSync('Build', arguments: timelineArgumentsIndicatingLandmarkEvent);
try {
_scheduledFlushDirtyElements = true;
if (callback != null) {
// ...
_dirtyElementsNeedsResorting = false;
try {
callback(); // 见 [2.5.4]
} finally {
// ...
}
}
// 对脏 elements 进行排序
_dirtyElements.sort(Element._sort);
_dirtyElementsNeedsResorting = false;
int dirtyCount = _dirtyElements.length;
int index = 0;
while (index < dirtyCount) {
// ...
try {
// 执行脏 element 的 rebuild 方法
_dirtyElements[index].rebuild();
} catch (e, stack) {
// ...
}
index += 1;
if (dirtyCount < _dirtyElements.length || _dirtyElementsNeedsResorting) {
_dirtyElements.sort(Element._sort);
_dirtyElementsNeedsResorting = false;
dirtyCount = _dirtyElements.length;
while (index > 0 && _dirtyElements[index - 1].dirty) {
index -= 1;
}
}
}
} finally {
// ...
}
}

2.5.4 RenderObjectToWidgetElement.mount

1
2
3
4
5
6
7
void mount(Element parent, dynamic newSlot) {
assert(parent == null);
// 见 [2.5.4.1]
super.mount(parent, newSlot);
// 见 [2.9]
_rebuild();
}

因为 RenderObjectToWidgetElement 对象是 element tree 的根节点,所以这里 parent 为 null.

2.5.4.1 RootRenderObjectElement.mount

1
2
3
4
5
6
7
void mount(Element parent, dynamic newSlot) {
// Root elements should never have parents.
assert(parent == null);
assert(newSlot == null);
// 见 [2.5.4.2]
super.mount(parent, newSlot);
}

2.5.4.2 RenderObjectElement.mount

1
2
3
4
5
6
7
8
9
10
11
void mount(Element parent, dynamic newSlot) {
// 见 [2.5.4.3]
super.mount(parent, newSlot);
// ...
// 见 [2.7]
_renderObject = widget.createRenderObject(this);
// ...
// 见 [2.8]
attachRenderObject(newSlot);
_dirty = false;
}

2.5.4.3 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
Element(Widget widget)
: assert(widget != null),
_widget = widget;

void mount(Element parent, dynamic newSlot) {
// ...
// 父 element
_parent = parent;
// 当前 element 的 slot
_slot = newSlot;
// root element 的 _depth 为 1,子 element 依次 +1
_depth = _parent != null ? _parent.depth + 1 : 1;
// 处于激活状态
_active = true;
// 只用 parent 的 _owner, 也就是说所有 element tree 的上节点公用一个 _owner
if (parent != null) // Only assign ownership if the parent is non-null
_owner = parent.owner;
// widget 是构造方法中赋值的,也就是 [2.5.1] 中的 RenderObjectToWidgetAdapter, 所以 key 就是 [2.5.1] 中的 GlobalObjectKey(container), 见 [2.6]
final Key key = widget.key;
if (key is GlobalKey) {
// 见 [2.6]
key._register(this);
}
_updateInheritance();
// ...
}

2.6 GlobalKey._register

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// src/widgets/framework.dart
@optionalTypeArgs
abstract class GlobalKey<T extends State<StatefulWidget>> extends Key {
const GlobalKey.constructor() : super.empty();
static final Map<GlobalKey, Element> _registry = <GlobalKey, Element>{};

// 将当前 Key 对象和 Element 对象关联起来,this 就是当前 key 对象
void _register(Element element) {
_registry[this] = element;
}

void _unregister(Element element) {
if (_registry[this] == element)
_registry.remove(this);
}
}

由 [2.5.4.3] 可知,这里是 GlobalObjectKey 类型的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// src/widgets/framework.dart
class GlobalObjectKey<T extends State<StatefulWidget>> extends GlobalKey<T> {
/// Creates a global key that uses [identical] on [value] for its [operator==].
const GlobalObjectKey(this.value) : super.constructor();

/// The object whose identity is used by this key's [operator==].
final Object value;

@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType)
return false;
return other is GlobalObjectKey<T>
&& identical(other.value, value);
}

@override
int get hashCode => identityHashCode(value);
// ...
}

由 [2.5.1] 可知,value 就是 [2.3.3.2] 的 renderView 对象,说明 GlobalObjectKey 是用来处理 render tree 和 element tree 之间的节点关系。

2.7 createRenderObject

1
RenderObjectWithChildMixin<T> createRenderObject(BuildContext context) => container;

将 [2.3.6.2] 的 renderView 对象赋值给 _renderObject

2.8 attachRenderObject

1
2
3
4
5
6
7
8
9
10
11
void attachRenderObject(dynamic newSlot) {
assert(_ancestorRenderObjectElement == null);
_slot = newSlot;
// 选择此 element tree 的祖先节点,此时为 null.
_ancestorRenderObjectElement = _findAncestorRenderObjectElement();
// 向 element 树中插入刚刚创建的 renderObject
_ancestorRenderObjectElement?.insertRenderObjectChild(renderObject, newSlot);
final ParentDataElement<ParentData> parentDataElement = _findAncestorParentDataElement();
if (parentDataElement != null)
_updateParentData(parentDataElement.widget);
}

此时 newSlot _ancestorRenderObjectElement _slot 均为 null, 同上,后面的 _ancestorRenderObjectElement parentDataElement 也为 null.

2.9 _rebuild

1
2
3
4
5
6
7
8
void _rebuild() {
try {
// 见 [2.9.1]
_child = updateChild(_child, widget.child, _rootChildSlot);
} catch (exception, stack) {
// ...
}
}

该方法的相关入参

  • _child: 第一次执行,_child 为 null
  • widget.child: widget: RenderObjectToWidgetAdapter 对象,所以 widget.child 就是 [2.4.1] 中我们在 main.dart 中自定义的 root widget
  • _rootChildSlot: static const Object _rootChildSlot = Object(); 是一个常量,表示一个 element 只有一个 child

2.9.1 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, dynamic newSlot) {
if (newWidget == null) {
if (child != null)
// 移除旧的 element
deactivateChild(child);
return null;
}
Element newChild;
if (child != null) {
bool hasSameSuperclass = true;
// ...
if (hasSameSuperclass && child.widget == newWidget) {
if (child.slot != newSlot)
// 更新 element
updateSlotForChild(child, newSlot);
newChild = child;
} else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) {
if (child.slot != newSlot)
// 更新 element
updateSlotForChild(child, newSlot);
// 更新 widget
child.update(newWidget);
newChild = child;
} else {
newChild = inflateWidget(newWidget, newSlot);
}
} else {
// 见 [2.9.2]
newChild = inflateWidget(newWidget, newSlot);
}

return newChild;
}

2.9.2 Element.inflateWidget

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Element inflateWidget(Widget newWidget, dynamic newSlot) {
final Key key = newWidget.key;
if (key is GlobalKey) {
// 从 _inactiveElements 中找可复用的 element
final Element newChild = _retakeInactiveElement(key, newWidget);
if (newChild != null) {
// 激活
newChild._activateWithParent(this, newSlot);
final Element updatedChild = updateChild(newChild, newWidget, newSlot);
return updatedChild;
}
}
// 创建 element, 见 [2.9.3], 这里是 StatefulElement
final Element newChild = newWidget.createElement();
// 见 [2.9.4]
newChild.mount(this, newSlot);
return newChild;
}

这里 key 为 null.

2.9.3 createElement

这个的 root widget 是 StatefulWidget 类型,所以会走

1
2
3
4
5
6
class StatefulElement extends ComponentElement {
StatefulElement(StatefulWidget widget) : _state = widget.createState(), super(widget) {
_state._element = this;
_state._widget = widget;
}
}

上面的方法主要功能

  • 对 _state 赋值
  • 对 element 的 widget 赋值,见前面的 2.5.4.3 Element.mount
  • 对 _state._element 赋值
  • 对 _state._widget 赋值

由此看见, state 是一个桥接类,关联 element 和 widget.

2.9.4 ComponentElement.mount

1
2
3
4
5
6
7
8
9
10
@override
void mount(Element parent, dynamic newSlot) {
// 见 [2.5.4.3], 不过这里 parent 有值,是 [2.5.4] 新建的 RenderObjectToWidgetElement(root element)
super.mount(parent, newSlot);
assert(_child == null);
assert(_active);
// 见 [2.9.5]
_firstBuild();
assert(_child != null);
}

StatefulElement extends ComponentElement extends Element, ComponentElement 是跟 2.5.4.2 RenderObjectElement 是同级别的子类。

2.9.5 ComponentElement._firstBuild

1
2
3
4
void _firstBuild() {
// 见 [2.9.5.1]
rebuild();
}

2.9.5.1 Element.rebuild

1
2
3
4
5
6
7
void rebuild() {
// 未被激活(没调用 mount 方法) 或者 没被标脏(没调用相关 update 方法或者 markNeedsBuild 方法),则不会走下面的逻辑
if (!_active || !_dirty)
return;
// 见 [2.9.5.2]
performRebuild();
}

2.9.5.2 StatefulElement.performRebuild

1
2
3
4
5
6
7
8
9
10
void performRebuild() {
// 只有调用当前类的 didChangeDependencies 方法,才会将 _didChangeDependencies 置为 true
if (_didChangeDependencies) {
// 调用 state didChangeDependencies 方法
_state.didChangeDependencies();
_didChangeDependencies = false;
}
// 见 [2.9.5.3]
super.performRebuild();
}

2.9.5.3 ComponentElement.performRebuild

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void performRebuild() {
Widget built;
try {
// 见 [2.9.5.4]
built = build();
} finally {
// 已 build, 后续不要再构建
_dirty = false;
}

try {
// 同 [2.9.1], 第一次 _child 为 null
_child = updateChild(_child, built, slot);
}
}

2.9.5.4 build

1
Widget build() => _state.build(this);

自此,最终会调用 rootwidget, 即 _MyAppState 的 build 方法。

2.10 scheduleWarmUpFrame

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
void scheduleWarmUpFrame() {
if (_warmUpFrame || schedulerPhase != SchedulerPhase.idle)
return;

_warmUpFrame = true;
Timeline.startSync('Warm-up frame');
final bool hadScheduledFrame = _hasScheduledFrame;
// 异步执行, 执行完上面的代码才会执行 `2.4.1 attachRootWidget`
// We use timers here to ensure that microtasks flush in between.
Timer.run(() {
assert(_warmUpFrame);
handleBeginFrame(null);
});
Timer.run(() {
assert(_warmUpFrame);
handleDrawFrame();
// We call resetEpoch after this frame so that, in the hot reload case,
// the very next frame pretends to have occurred immediately after this
// warm-up frame. The warm-up frame's timestamp will typically be far in
// the past (the time of the last real frame), so if we didn't reset the
// epoch we would see a sudden jump from the old time in the warm-up frame
// to the new time in the "real" frame. The biggest problem with this is
// that implicit animations end up being triggered at the old time and
// then skipping every frame and finishing in the new time.
resetEpoch();
_warmUpFrame = false;
if (hadScheduledFrame)
scheduleFrame();
});

// Lock events so touch events etc don't insert themselves until the
// scheduled frame has finished.
lockEvents(() async {
await endOfFrame;
Timeline.finishSync();
});
}

进行绘制操作。

3. 总结

从 2.1 的 runApp 入口可知,

  1. WidgetsFlutterBinding 初始化,这是一个单例,负责创建各种绑定对象,有的时候我们需要将这段代码前置,使得各种绑定操作在 runApp 之前完成;
  2. attachRootWidget, 自底向上遍历整个视图树,创建 element、renderObject 对象,建立 widget、element、renderObject 三者之间的关系;
  3. scheduleWarmUpFrame, 执行绘制操作

Q: 自底向上遍历整个视图树的时候,感觉 mount 无线递归执行,什么时候完成呢?
A: 当遍历到最顶层的 widget 时,在调用 updateChild 的时候回返回 null, 也就是的结束,从而回来,然后回到 2.5 attachToRenderTree,返回 RenderObjectToWidgetElement 类型的 root element. 我把前面 demo 的 debug 流程贴出来,如下:

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
RenderObjectToWidgetElement 
- mount // parent: null, newSlot: null
- _rebuild
- updateChild // child: null, newWidget: MyApp
- inflateWidget // newWidget: MyApp
- createElement // StatefulElement: ComponentElement
- mount

StatefulElement: ComponentElement
- mount // parent: [root](renderObject: RenderView#5a380 NEEDS-LAYOUT NEEDS-PAINT)
- _firstBuild
- rebuild
- performRebuild
- updateChild // child: null, newWidget: Container
- inflateWidget // newWidget: Container
- createElement // StatelessElement: ComponentElement
- mount //

StatelessElement: ComponentElement
- mount // parent: MyApp(state: _MyAppState#9e4bc)
- _firstBuild
- rebuild
- performRebuild // StatelessElement.build
- updateChild // child: null, newWidget: LimitedBox
- inflateWidget // newWidget: LimitedBox(maxWidth: 0.0, maxHeight: 0.0)
- createElement // SingleChildRenderObjectElement: RenderObjectElement
- mount

SingleChildRenderObjectElement
- mount // parent: Container
- updateChild // child: null, newWidget: ConstrainedBox(BoxConstraints(biggest))
- inflateWidget // newWidget: ConstrainedBox(BoxConstraints(biggest))
- createElement // SingleChildRenderObjectElement: RenderObjectElement
- mount

SingleChildRenderObjectElement
- mount // parent: LimitedBox(maxWidth: 0.0, maxHeight: 0.0, renderObject: RenderLimitedBox#3d07c NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-U
- updateChild // child: null, newWidget: null

3.1 问题

  1. 三棵树的关系,element 的具体功能
  2. 不同 element 执行 build 方法的时机
  3. key slot 等联系
  4. 整个执行一帧的流程
  5. 页面刷新的具体流程,setState vs provider 局部刷新