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() { runApp( materialApp(), ); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State <MyApp > { Widget build(BuildContext context) { return Container(); } }
2. 启动流程 调试堆栈如下
2.1 runApp 1 2 3 4 5 6 void runApp(Widget app) { WidgetsFlutterBinding.ensureInitialized() ..scheduleAttachRootWidget(app) ..scheduleWarmUpFrame(); }
2.2 ensureInitialized 1 2 3 4 5 6 7 8 9 10 11 class WidgetsFlutterBinding extends BindingBase with GestureBinding , SchedulerBinding , ServicesBinding , PaintingBinding , SemanticsBinding , RendererBinding , WidgetsBinding { static WidgetsBinding ensureInitialized() { if (WidgetsBinding.instance == null ) WidgetsFlutterBinding(); return WidgetsBinding.instance; } }
2.2.1 BindingBase 初始化 1 2 3 4 5 6 7 8 BindingBase() { initInstances(); initServiceExtensions(); }
2.3 initInstances initInstances
方法的调用顺序是从右到左的,即
WidgetsBinding: The glue between the widgets layer and the Flutter engine.
RendererBinding: The glue between the render tree and the Flutter engine.
SemanticsBinding: The glue between the semantics layer and the Flutter engine.
PaintingBinding: Binding for the painting library.
ServicesBinding: Listens for platform messages and directs them to the [defaultBinaryMessenger].
SchedulerBinding: Scheduler for running the following: xxx.
GestureBinding: A binding for the gesture subsystem.
按照上面的顺序执行完 initInstances
中的 super.initInstances()
, 再按照上面的逆序执行各个 Binding
类 initInstances
中剩余逻辑,然后执行 initServiceExtensions
。
2.3.1 GestureBinding 1 2 3 4 5 6 7 void initInstances() { super .initInstances(); _instance = this ; window .onPointerDataPacket = _handlePointerDataPacket; }
2.3.2 SchedulerBinding 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void initInstances() { super .initInstances(); _instance = this ; 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 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 void initInstances() { super .initInstances(); _instance = this ; _imageCache = createImageCache(); shaderWarmUp?.execute(); }
2.3.5 SemanticsBinding 1 2 3 4 5 6 7 void initInstances() { super .initInstances(); _instance = this ; _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 void initInstances() { super .initInstances(); _instance = this ; _pipelineOwner = PipelineOwner( onNeedVisualUpdate: ensureVisualUpdate, onSemanticsOwnerCreated: _handleSemanticsOwnerCreated, onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed, ); window ..onMetricsChanged = handleMetricsChanged ..onTextScaleFactorChanged = handleTextScaleFactorChanged ..onPlatformBrightnessChanged = handlePlatformBrightnessChanged ..onSemanticsEnabledChanged = _handleSemanticsEnabledChanged ..onSemanticsAction = _handleSemanticsAction; initRenderView(); _handleSemanticsEnabledChanged(); assert (renderView != null ); addPersistentFrameCallback(_handlePersistentFrameCallback); initMouseTracker(); }
2.3.6.1 PipelineOwner 初始化 1 2 3 4 5 6 7 8 class PipelineOwner { PipelineOwner({ this .onNeedVisualUpdate, this .onSemanticsOwnerCreated, this .onSemanticsOwnerDisposed, }); }
用来管理 rendering pipeline 的类,在 rendering pipeline 过程中,会按序执行以下方法(这几个阶段的操作对象都是 render objects
)
flushLayout
flushCompositingBits
flushPaint
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(configuration: createViewConfiguration(), window : window ); renderView.prepareInitialFrame(); }
2.3.6.3 set renderView 1 2 3 4 5 6 7 8 class RenderView extends RenderObject with RenderObjectWithChildMixin <RenderBox > { set renderView(RenderView value) { assert (value != null ); _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 成员变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void initInstances() { super .initInstances(); _instance = this ; _buildOwner = BuildOwner(); 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 class BuildOwner { BuildOwner({ this .onBuildScheduled }); }
1 2 3 4 5 6 7 void scheduleAttachRootWidget(Widget rootWidget) { Timer.run(() { attachRootWidget(rootWidget); }); }
1 2 3 4 5 6 7 8 9 void attachRootWidget(Widget rootWidget) { _readyToProduceFrames = true ; _renderViewElement = RenderObjectToWidgetAdapter<RenderBox>( container: renderView, debugShortDescription: '[root]' , child: rootWidget, ).attachToRenderTree(buildOwner, renderViewElement as RenderObjectToWidgetElement<RenderBox>); }
该方法的主要参数
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).
)。
1 2 3 4 5 6 7 8 class RenderObjectToWidgetAdapter <T extends RenderObject > extends RenderObjectWidget { RenderObjectToWidgetAdapter({ this .child, this .container, 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(() { element = createElement(); assert (element != null ); element.assignOwner(owner); }); owner.buildScope(element, () { 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 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(); } finally { } } _dirtyElements.sort(Element ._sort); _dirtyElementsNeedsResorting = false ; int dirtyCount = _dirtyElements.length; int index = 0 ; while (index < dirtyCount) { try { _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 { } }
1 2 3 4 5 6 7 void mount(Element parent, dynamic newSlot) { assert (parent == null ); super .mount(parent, newSlot); _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) { assert (parent == null ); assert (newSlot == null ); 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) { super .mount(parent, newSlot); _renderObject = widget.createRenderObject(this ); 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) { _parent = parent; _slot = newSlot; _depth = _parent != null ? _parent.depth + 1 : 1 ; _active = true ; if (parent != null ) _owner = parent.owner; final Key key = widget.key; if (key is GlobalKey) { key._register(this ); } _updateInheritance(); }
2.6 GlobalKey._register 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @optionalTypeArgs abstract class GlobalKey <T extends State <StatefulWidget >> extends Key { const GlobalKey.constructor() : super .empty(); static final Map <GlobalKey, Element > _registry = <GlobalKey, Element >{}; 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 class GlobalObjectKey <T extends State <StatefulWidget >> extends GlobalKey <T > { const GlobalObjectKey(this .value) : super .constructor(); 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; _ancestorRenderObjectElement = _findAncestorRenderObjectElement(); _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 { _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 ) deactivateChild(child); return null ; } Element newChild; if (child != null ) { bool hasSameSuperclass = true ; if (hasSameSuperclass && child.widget == newWidget) { if (child.slot != newSlot) updateSlotForChild(child, newSlot); newChild = child; } else if (hasSameSuperclass && Widget.canUpdate(child.widget, newWidget)) { if (child.slot != newSlot) updateSlotForChild(child, newSlot); child.update(newWidget); newChild = child; } else { newChild = inflateWidget(newWidget, newSlot); } } else { newChild = inflateWidget(newWidget, newSlot); } return newChild; }
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) { final Element newChild = _retakeInactiveElement(key, newWidget); if (newChild != null ) { newChild._activateWithParent(this , newSlot); final Element updatedChild = updateChild(newChild, newWidget, newSlot); return updatedChild; } } final Element newChild = newWidget.createElement(); 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) { super .mount(parent, newSlot); assert (_child == null ); assert (_active); _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() { rebuild(); }
2.9.5.1 Element.rebuild 1 2 3 4 5 6 7 void rebuild() { if (!_active || !_dirty) return ; performRebuild(); }
1 2 3 4 5 6 7 8 9 10 void performRebuild() { if (_didChangeDependencies) { _state.didChangeDependencies(); _didChangeDependencies = false ; } super .performRebuild(); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void performRebuild() { Widget built; try { built = build(); } finally { _dirty = false ; } try { _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; Timer.run(() { assert (_warmUpFrame); handleBeginFrame(null ); }); Timer.run(() { assert (_warmUpFrame); handleDrawFrame(); resetEpoch(); _warmUpFrame = false ; if (hadScheduledFrame) scheduleFrame(); }); lockEvents(() async { await endOfFrame; Timeline.finishSync(); }); }
进行绘制操作。
3. 总结 从 2.1 的 runApp 入口可知,
WidgetsFlutterBinding 初始化,这是一个单例,负责创建各种绑定对象,有的时候我们需要将这段代码前置,使得各种绑定操作在 runApp 之前完成;
attachRootWidget, 自底向上遍历整个视图树,创建 element、renderObject 对象,建立 widget、element、renderObject 三者之间的关系;
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 问题
三棵树的关系,element 的具体功能
不同 element 执行 build 方法的时机
key slot 等联系
整个执行一帧的流程
页面刷新的具体流程,setState vs provider 局部刷新