0%

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 局部刷新

本文基于 flutter 1.22.2 源码,在 ios_debug_unopt 产物下调试。

1. 概述

本文下面的 demo(来自 Writing custom platform-specific code) 和 flutter 源码来分析 ios platform channels 的实现。

1.1 demo

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
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
...
class _MyHomePageState extends State<MyHomePage> {
static const platform = const MethodChannel('samples.flutter.dev/battery');

// Get battery level.
String _batteryLevel = 'Unknown battery level.';

Future<void> _getBatteryLevel() async {
String batteryLevel;
try {
final int result = await platform.invokeMethod('getBatteryLevel');
batteryLevel = 'Battery level at $result % .';
} on PlatformException catch (e) {
batteryLevel = "Failed to get battery level: '${e.message}'.";
}

setState(() {
_batteryLevel = batteryLevel;
});
}
}
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
#import <Flutter/Flutter.h>
#import "GeneratedPluginRegistrant.h"

@implementation AppDelegate
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController;

FlutterMethodChannel* batteryChannel = [FlutterMethodChannel
methodChannelWithName:@"samples.flutter.dev/battery"
binaryMessenger:controller.binaryMessenger];

__weak typeof(self) weakSelf = self;
[batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
// Note: this method is invoked on the UI thread.
if ([@"getBatteryLevel" isEqualToString:call.method]) {
int batteryLevel = [weakSelf getBatteryLevel];

if (batteryLevel == -1) {
result([FlutterError errorWithCode:@"UNAVAILABLE"
message:@"Battery info unavailable"
details:nil]);
} else {
result(@(batteryLevel));
}
} else {
result(FlutterMethodNotImplemented);
}
}];

[GeneratedPluginRegistrant registerWithRegistry:self];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (int)getBatteryLevel {
UIDevice* device = UIDevice.currentDevice;
device.batteryMonitoringEnabled = YES;
if (device.batteryState == UIDeviceBatteryStateUnknown) {
return -1;
} else {
return (int)(device.batteryLevel * 100);
}
}

2. Dart 层

2.1 MethodChannel 初始化

flutter/packages/flutter/lib/src/services/platform_channel.dart

1
2
3
4
5
/// A named channel for communicating with platform plugins using asynchronous method calls.
const MethodChannel(this.name, [this.codec = const StandardMethodCodec(), BinaryMessenger? binaryMessenger ])
: assert(name != null),
assert(codec != null),
_binaryMessenger = binaryMessenger;

初始化,默认是使用标准编解码器 StandardMethodCodec,在发送到 platform plugin 要使用 codec 进行编码,同样 platform plugin 发送过来的消息要解码成 Dart 层的数据。所以,platform plugin 那边需要兼容 Dart 层的 codec

2.2 MessageCodec 抽象类

flutter/packages/flutter/lib/src/services/message_codec.dart

1
2
3
4
5
/// A message encoding/decoding mechanism.
abstract class MessageCodec<T> {
ByteData? encodeMessage(T message);
T decodeMessage(ByteData? message);
}

StandardMethodCodec 实现了抽象类 MessageCodec 的编解码方法。

-w755

从上图可知,目标有四个类实现了 MessageCodec

  • BinaryCodec: [MessageCodec] with unencoded binary messages represented using [ByteData]. // 没编码的原始二进制数据类型
  • JSONMessageCodec: [MessageCodec] with UTF-8 encoded JSON messages. // utf-8 编码的 json 消息
  • StandardMessageCodec: [MessageCodec] using the Flutter standard binary encoding. // flutter 标准的二进制编码,可以参考 Writing custom platform-specific codePlatform channel data types support and codecs 小节,当然 class StandardMessageCodec implements MessageCodec<dynamic> { 定义上面的注释也有解释。
  • StringCodec: [MessageCodec] with UTF-8 encoded String messages. // utf-8 编码的字符串消息

2.3 invokeMethod

flutter/packages/flutter/lib/src/services/platform_channel.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Future<T?> invokeMethod<T>(String method, [ dynamic arguments ]) {
return _invokeMethod<T>(method, missingOk: false, arguments: arguments);
}

@optionalTypeArgs
Future<T?> _invokeMethod<T>(String method, { required bool missingOk, dynamic arguments }) async {
assert(method != null);
// 见 2.6
final ByteData? result = await binaryMessenger.send(
name,
codec.encodeMethodCall(MethodCall(method, arguments)),
);
if (result == null) {
if (missingOk) {
return null;
}
throw MissingPluginException('No implementation found for method $method on channel $name');
}
// 见 [6.6]
return codec.decodeEnvelope(result) as T;
}

该方法主要功能:

  1. 创建 MethodCall 对象[见 2.3.1]
  2. 调用 StandardMessageCodec 的 encodeMethodCall, 将 MethodCall 对象编码成 ByteData 数据[见 2.3.2]
  3. 调用 BinaryMessenger 来发送 ByteData 数据 [见 2.4]
  4. 调用 StandardMessageCodec 的 decodeEnvelope, 将发送返回后的结果进行解码

2.3.1 MethodCall初始化

flutter/packages/flutter/lib/src/services/message_codec.dart

1
2
const MethodCall(this.method, [this.arguments])
: assert(method != null); // 方法名,非空

这里的参数就是 invokeMethod 方法的入参 methodarguments

2.3.2 encodeMethodCall

flutter/packages/flutter/lib/src/services/message_codec.dart

来自抽象类 MethodCodec, 对方法调用和结果进行编解码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/// A codec for method calls and enveloped results.
abstract class MethodCodec {
/// Encodes the specified [methodCall] into binary.
ByteData encodeMethodCall(MethodCall methodCall);

/// Decodes the specified [methodCall] from binary.
MethodCall decodeMethodCall(ByteData? methodCall);

/// Decodes the specified result [envelope] from binary.
dynamic decodeEnvelope(ByteData envelope);

/// Encodes a successful [result] into a binary envelope.
ByteData encodeSuccessEnvelope(dynamic result);

/// Encodes an error result into a binary envelope.
ByteData encodeErrorEnvelope({ required String code, String? message, dynamic details});
}

flutter/packages/flutter/lib/src/services/message_codecs.dart

1
2
3
4
5
6
7
8
9
@override
ByteData encodeMethodCall(MethodCall call) {
// 创建一个写buffer, 见 [2.3.3]
final WriteBuffer buffer = WriteBuffer();
// 调用 StandardMessageCodec 的 writeValue 方法,将数据写入 buffer
messageCodec.writeValue(buffer, call.method);
messageCodec.writeValue(buffer, call.arguments);
return buffer.done();
}

2.3.3 WriteBuffer

flutter/packages/flutter/lib/src/foundation/serialization.dart

1
2
3
4
5
6
7
8
9
10
11
12
WriteBuffer()
: _buffer = Uint8Buffer(),
_eightBytes = ByteData(8) {
_eightBytesAsList = _eightBytes.buffer.asUint8List();
}

ByteData done() {
final ByteData result = _buffer!.buffer.asByteData(0, _buffer!.lengthInBytes);
_buffer = null;
// 返回最后的写入结果
return result;
}

2.4 binaryMessenger.send

flutter/packages/flutter/lib/src/services/platform_channel.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
BinaryMessenger get binaryMessenger => _binaryMessenger ?? defaultBinaryMessenger;

BinaryMessenger get defaultBinaryMessenger {
assert(() {
if (ServicesBinding.instance == null) {
throw FlutterError(
'ServicesBinding.defaultBinaryMessenger was accessed before the '
'binding was initialized.\n'
"If you're running an application and need to access the binary "
'messenger before `runApp()` has been called (for example, during '
'plugin initialization), then you need to explicitly call the '
'`WidgetsFlutterBinding.ensureInitialized()` first.\n'
"If you're running a test, you can call the "
'`TestWidgetsFlutterBinding.ensureInitialized()` as the first line in '
"your test's `main()` method to initialize the binding."
);
}
return true;
}());
// 见 [2.4.1]
return ServicesBinding.instance!.defaultBinaryMessenger;
}

由于 MethodChannel 初始化的时候没有传 BinaryMessenger 对象,所以这里是用的默认值:ServicesBinding.instance!.defaultBinaryMessenger.

2.4.1 _sendPlatformMessage

flutter/packages/flutter/lib/src/services/binding.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class _DefaultBinaryMessenger extends BinaryMessenger {
const _DefaultBinaryMessenger._();
Future<ByteData?> _sendPlatformMessage(String channel, ByteData? message) {
// 见 [2.4.2]
final Completer<ByteData?> completer = Completer<ByteData?>();
// ui.window is accessed directly instead of using ServicesBinding.instance.window
// because this method might be invoked before any binding is initialized.
// This issue was reported in #27541. It is not ideal to statically access
// ui.window because the Window may be dependency injected elsewhere with
// a different instance. However, static access at this location seems to be
// the least bad option.
// 见 [2.5]
ui.window.sendPlatformMessage(channel, message, (ByteData? reply) {
try {
// 见 [3.1.1], 会在 engine 层保存起来
completer.complete(reply);
} catch (exception, stack) {
// ...
});
return completer.future;
}
}

2.4.2 Completer 初始化

flutter/bin/cache/pkg/sky_engine/lib/async/future.dart

1
2
// 见 [2.4.3]
factory Completer() => new _AsyncCompleter<T>();

2.4.3 _AsyncCompleter 初始化

flutter/bin/cache/pkg/sky_engine/lib/async/future_impl.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
abstract class _Completer<T> implements Completer<T> {
final _Future<T> future = new _Future<T>();

void complete([FutureOr<T>? value]);

void _completeError(Object error, StackTrace stackTrace);

// The future's _isComplete doesn't take into account pending completions.
// We therefore use _mayComplete.
bool get isCompleted => !future._mayComplete;
}

class _AsyncCompleter<T> extends _Completer<T> {
void complete([FutureOr<T>? value]) {
if (!future._mayComplete) throw new StateError("Future already completed");
// 见 [6.5]
future._asyncComplete(value == null ? value as dynamic : value);
}
}

2.5 window.sendPlatformMessage

flutter/bin/cache/pkg/sky_engine/lib/ui/window.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
void sendPlatformMessage(String name,
ByteData? data,
PlatformMessageResponseCallback? callback) {
// 见[2.5.1]
final String? error =
_sendPlatformMessage(name, _zonedPlatformMessageResponseCallback(callback), data);
if (error != null)
throw Exception(error);
}
// 见 [3.1]
String? _sendPlatformMessage(String name,
PlatformMessageResponseCallback? callback,
ByteData? data) native 'PlatformConfiguration_sendPlatformMessage';

_sendPlatformMessage 是一个 Native 代码,会调用到引擎层。

2.5.1 _zonedPlatformMessageResponseCallback

flutter/bin/cache/pkg/sky_engine/lib/ui/window.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
/// Wraps the given [callback] in another callback that ensures that the
/// original callback is called in the zone it was registered in.
static PlatformMessageResponseCallback? _zonedPlatformMessageResponseCallback(PlatformMessageResponseCallback? callback) {
if (callback == null)
return null;

// Store the zone in which the callback is being registered.
final Zone registrationZone = Zone.current;

return (ByteData? data) {
registrationZone.runUnaryGuarded(callback, data);
};
}

将当前注册回调的 Zone.current 存起来。

3. engine 层

3.1 _SendPlatformMessage

engine/src/flutter/lib/ui/window/platform_configuration.cc

在 flutter 源码中搜索 _sendPlatformMessage

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
// platform_configuration.cc -L137
void _SendPlatformMessage(Dart_NativeArguments args) {
tonic::DartCallStatic(&SendPlatformMessage, args);
}

// platform_configuration.cc -L105
Dart_Handle SendPlatformMessage(Dart_Handle window,
const std::string& name,
Dart_Handle callback,
Dart_Handle data_handle) {
// 获取当前 dart_state
UIDartState* dart_state = UIDartState::Current();
// 没有 platform_configuration, 抛出异常
if (!dart_state->platform_configuration()) {
return tonic::ToDart(
"Platform messages can only be sent from the main isolate");
}

fml::RefPtr<PlatformMessageResponse> response;
if (!Dart_IsNull(callback)) {
// 见 [3.1.1] 和 [3.1.2]
response = fml::MakeRefCounted<PlatformMessageResponseDart>(
tonic::DartPersistentValue(dart_state, callback),
dart_state->GetTaskRunners().GetUITaskRunner());
}
if (Dart_IsNull(data_handle)) {
dart_state->platform_configuration()->client()->HandlePlatformMessage(
fml::MakeRefCounted<PlatformMessage>(name, response));
} else {
tonic::DartByteData data(data_handle);
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
// 见 [3.2]
dart_state->platform_configuration()->client()->HandlePlatformMessage(
fml::MakeRefCounted<PlatformMessage>(
name, std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()),
response));
}

return Dart_Null();
}

该方法主要功能:

  1. 发送平台消息,只允许在主 isolate 中发出,否则会抛出异常
  2. 相关参数
    1. window: Dart 层的 window
    2. name: channel 名
    3. callback: 见 [3.1.1] 的描述
    4. data_handle: 编码后的 MethodCall 对象,也就是待执行的方法和参数,后续赋值给 PlatformMessage 对象的 data 成员变量
  3. 创建 PlatformMessageResponseDart 对象,保存 callback 和 GetUITaskRunner
  4. 调用 RuntimeController 的 HandlePlatformMessage 方法,入参为 PlatformMessage, 见 [3.1.3]

3.1.1 DartPersistentValue

1
2
3
4
5
6
7
8
9
10
11
12
13
// dart_persistent_value.cc -L20
DartPersistentValue::DartPersistentValue(DartState* dart_state,
Dart_Handle value)
: value_(nullptr) {
Set(dart_state, value);
}

// dart_persistent_value.cc -L30
void DartPersistentValue::Set(DartState* dart_state, Dart_Handle value) {
TONIC_DCHECK(is_empty());
dart_state_ = dart_state->GetWeakPtr();
value_ = Dart_NewPersistentHandle(value);
}

dart_statecallback 封装成 DartPersistentValue 对象,这里的 callback 就是 [2.4] 中的 completer.complete(reply);,处理发送返回的数据。

3.1.2 PlatformMessageResponseDart 初始化

engine/src/flutter/lib/ui/window/platform_message_response_dart.cc

1
2
3
4
5
PlatformMessageResponseDart::PlatformMessageResponseDart(
tonic::DartPersistentValue callback,
fml::RefPtr<fml::TaskRunner> ui_task_runner)
: callback_(std::move(callback)),
ui_task_runner_(std::move(ui_task_runner)) {}

简单的赋初始值。

3.1.3 PlatformMessage 初始化

1
2
3
4
5
6
7
8
// platform_message.cc -L11
PlatformMessage::PlatformMessage(std::string channel,
std::vector<uint8_t> data,
fml::RefPtr<PlatformMessageResponse> response)
: channel_(std::move(channel)),
data_(std::move(data)),
hasData_(true),
response_(std::move(response)) {}

该方法相关入参

  • channel: channel 名
  • data: data_handle(见 [3.1] 的描述) 转换后的值
  • response: 见 [3.1.1], 对 3.1.1callback 的封装

至此, Dart 层传过来的数据以及在 engine 层转换后的数据,都封装在了 PlatformMessage 对象中,后续在 engine 层都是操作该 PlatformMessage 对象。

3.2 RuntimeController::HandlePlatformMessage

engine/src/flutter/runtime/runtime_controller.cc

1
2
3
4
5
6
7
// |PlatformConfigurationClient|
// runtime_controller.cc -L328
void RuntimeController::HandlePlatformMessage(
fml::RefPtr<PlatformMessage> message) {
// 见 3.3
client_.HandlePlatformMessage(std::move(message));
}

note: 这块的逻辑代码需要了解 flutter 的引擎启动。

相关调用链在

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
48
49
50
51
52
53
54
55
56
57
// runtime_controller.cc -L64
RuntimeController::RuntimeController(
RuntimeDelegate& p_client,
DartVM* p_vm,
fml::RefPtr<const DartSnapshot> p_isolate_snapshot,
TaskRunners p_task_runners,
fml::WeakPtr<SnapshotDelegate> p_snapshot_delegate,
fml::WeakPtr<HintFreedDelegate> p_hint_freed_delegate,
fml::WeakPtr<IOManager> p_io_manager,
fml::RefPtr<SkiaUnrefQueue> p_unref_queue,
fml::WeakPtr<ImageDecoder> p_image_decoder,
std::string p_advisory_script_uri,
std::string p_advisory_script_entrypoint,
const std::function<void(int64_t)>& idle_notification_callback,
const PlatformData& p_platform_data,
const fml::closure& p_isolate_create_callback,
const fml::closure& p_isolate_shutdown_callback,
std::shared_ptr<const fml::Mapping> p_persistent_isolate_data)
: client_(p_client),
vm_(p_vm),
isolate_snapshot_(std::move(p_isolate_snapshot)),
task_runners_(p_task_runners),
snapshot_delegate_(p_snapshot_delegate),
hint_freed_delegate_(p_hint_freed_delegate),
io_manager_(p_io_manager),
unref_queue_(p_unref_queue),
image_decoder_(p_image_decoder),
advisory_script_uri_(p_advisory_script_uri),
advisory_script_entrypoint_(p_advisory_script_entrypoint),
idle_notification_callback_(idle_notification_callback),
platform_data_(std::move(p_platform_data)),
isolate_create_callback_(p_isolate_create_callback),
isolate_shutdown_callback_(p_isolate_shutdown_callback),
persistent_isolate_data_(std::move(p_persistent_isolate_data)) {
// Create the root isolate as soon as the runtime controller is initialized.
// It will be run at a later point when the engine provides a run
// configuration and then runs the isolate.
auto strong_root_isolate =
DartIsolate::CreateRootIsolate(
vm_->GetVMData()->GetSettings(), //
isolate_snapshot_, //
task_runners_, //
std::make_unique<PlatformConfiguration>(this), //
snapshot_delegate_, //
hint_freed_delegate_, //
io_manager_, //
unref_queue_, //
image_decoder_, //
p_advisory_script_uri, //
p_advisory_script_entrypoint, //
nullptr, //
isolate_create_callback_, //
isolate_shutdown_callback_ //
)
.lock();
// ...
}

std::make_unique<PlatformConfiguration>(this): 将当前 RuntimeController 对象作为入参初始化 PlatformConfiguration 对象(赋值给 client_ 成员变量)。

3.3 Engine::HandlePlatformMessage

1
2
3
4
5
6
7
8
9
// engine.cc -L496
void Engine::HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) {
if (message->channel() == kAssetChannel) {
HandleAssetPlatformMessage(std::move(message));
} else {
// 见 [3.4]
delegate_.OnEngineHandlePlatformMessage(std::move(message));
}
}

相关调用链在

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
// engine.cc -L59
Engine::Engine(Delegate& delegate,
const PointerDataDispatcherMaker& dispatcher_maker,
DartVM& vm,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
TaskRunners task_runners,
const PlatformData platform_data,
Settings settings,
std::unique_ptr<Animator> animator,
fml::WeakPtr<IOManager> io_manager,
fml::RefPtr<SkiaUnrefQueue> unref_queue,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate)
: Engine(delegate,
dispatcher_maker,
vm.GetConcurrentWorkerTaskRunner(),
task_runners,
settings,
std::move(animator),
io_manager,
nullptr) {
runtime_controller_ = std::make_unique<RuntimeController>(
*this, // runtime delegate
&vm, // VM
std::move(isolate_snapshot), // isolate snapshot
task_runners_, // task runners
std::move(snapshot_delegate), // snapshot delegate
GetWeakPtr(), // hint freed delegate
std::move(io_manager), // io manager
std::move(unref_queue), // Skia unref queue
image_decoder_.GetWeakPtr(), // image decoder
settings_.advisory_script_uri, // advisory script uri
settings_.advisory_script_entrypoint, // advisory script entrypoint
settings_.idle_notification_callback, // idle notification callback
platform_data, // platform data
settings_.isolate_create_callback, // isolate create callback
settings_.isolate_shutdown_callback, // isolate shutdown callback
settings_.persistent_isolate_data // persistent isolate data
);
}

std::make_unique<RuntimeController>(: 将当前 engine 对象作为入参初始化 RuntimeController 对象(赋值给 client_ 成员变量)。

3.4 Shell::OnEngineHandlePlatformMessage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// |Engine::Delegate|
void Shell::OnEngineHandlePlatformMessage(
fml::RefPtr<PlatformMessage> message) {
FML_DCHECK(is_setup_);
FML_DCHECK(task_runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());

if (message->channel() == kSkiaChannel) {
HandleEngineSkiaMessage(std::move(message));
return;
}

// 在 Platform 线程中执行任务
task_runners_.GetPlatformTaskRunner()->PostTask(
[view = platform_view_->GetWeakPtr(), message = std::move(message)]() {
if (view) {
// 见 [3.5]
view->HandlePlatformMessage(std::move(message));
}
});
}

相关调用链在

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
// shell.cc -L152
fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetUITaskRunner(),
fml::MakeCopyable([&engine_promise, //
shell = shell.get(), //
&dispatcher_maker, //
&platform_data, //
isolate_snapshot = std::move(isolate_snapshot), //
vsync_waiter = std::move(vsync_waiter), //
&weak_io_manager_future, //
&snapshot_delegate_future, //
&unref_queue_future //
]() mutable {
TRACE_EVENT0("flutter", "ShellSetupUISubsystem");
const auto& task_runners = shell->GetTaskRunners();

// The animator is owned by the UI thread but it gets its vsync pulses
// from the platform.
auto animator = std::make_unique<Animator>(*shell, task_runners,
std::move(vsync_waiter));

engine_promise.set_value(std::make_unique<Engine>(
*shell, //
dispatcher_maker, //
*shell->GetDartVM(), //
std::move(isolate_snapshot), //
task_runners, //
platform_data, //
shell->GetSettings(), //
std::move(animator), //
weak_io_manager_future.get(), //
unref_queue_future.get(), //
snapshot_delegate_future.get() //
));
}));

std::make_unique<Engine>(: 将 *shell 指针作为入参初始化 Engine 对象(赋值给 delegate_ 成员变量)。

3.5 PlatformViewIOS::HandlePlatformMessage

1
2
3
4
5
6
// |PlatformView|
// platform_view_ios.mm -L61
void PlatformViewIOS::HandlePlatformMessage(fml::RefPtr<flutter::PlatformMessage> message) {
// 见 [3.6]
platform_message_router_.HandlePlatformMessage(std::move(message));
}

platform_view_

相关调用链如下

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
// shell.cc -L544, 给 platform_view_ 赋值
bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
std::unique_ptr<Engine> engine,
std::unique_ptr<Rasterizer> rasterizer,
std::unique_ptr<ShellIOManager> io_manager) {
// ...
platform_view_ = std::move(platform_view);
// ...
}

// shell.cc -L167
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
DartVMRef vm,
TaskRunners task_runners,
const PlatformData platform_data,
Settings settings,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
const Shell::CreateCallback<PlatformView>& on_create_platform_view,
const Shell::CreateCallback<Rasterizer>& on_create_rasterizer) {
// ...
// 获取 platform_view
auto platform_view = on_create_platform_view(*shell.get());

// ...
if (!shell->Setup(std::move(platform_view), //
engine_future.get(), //
rasterizer_future.get(), //
io_manager_future.get()) //
) {
return nullptr;
}
// ...
}

// FlutterEngine.mm -L513
- (BOOL)createShell:(NSString*)entrypoint
libraryURI:(NSString*)libraryURI
initialRoute:(NSString*)initialRoute {
// ...
// on_create_platform_view 回调
flutter::Shell::CreateCallback<flutter::PlatformView> on_create_platform_view =
[](flutter::Shell& shell) {
return std::make_unique<flutter::PlatformViewIOS>(
shell, flutter::GetRenderingAPIForProcess(), shell.GetTaskRunners());
};
// ...
}

3.6 PlatformMessageRouter::HandlePlatformMessage

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
// platform_message_router.mm -L17
void PlatformMessageRouter::HandlePlatformMessage(
fml::RefPtr<flutter::PlatformMessage> message) const {
// [3.1.2] 中的 PlatformMessageResponseDart 对象
fml::RefPtr<flutter::PlatformMessageResponse> completer = message->response();
// message->channel(): [3.1] 中的 channel 名
auto it = message_handlers_.find(message->channel());
if (it != message_handlers_.end()) {
FlutterBinaryMessageHandler handler = it->second;
NSData* data = nil;
if (message->hasData()) {
// 由 [3.1.3] 可知, message->data() 就是编码后的 `MethodCall` 对象
data = GetNSDataFromVector(message->data());
}
// 见 [5.4]
handler(data, ^(NSData* reply) {
if (completer) {
if (reply) {
// 见 [6.1]
completer->Complete(GetMappingFromNSData(reply));
} else {
completer->CompleteEmpty();
}
}
});
} else {
if (completer) {
completer->CompleteEmpty();
}
}
}

该方法注意功能:

  1. 根据 channel 名在 message_handlers_ unordered_map 中找到对应的 FlutterBinaryMessageHandler 类型的 handler
  2. 调用 handler 回调方法获取 reply 数据
  3. 将 reply 数据作为入参,调用 PlatformMessageResponseDart 对象的 Complete 方法

现在的问题是, FlutterBinaryMessageHandler 类型的 handler 是在哪里赋值的,也就是什么时候调用 [4.4] 的方法,详见下一小节:[4]。

4. shell 层

note: 这块的逻辑代码需要了解 flutter 的引擎启动。
在创建 engine 的时候,会设置 engine 层相关的 channel.

engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm

1
2
3
4
5
6
7
8
9
10
11
// FlutterEngine.mm  -L541
- (BOOL)createShell:(NSString*)entrypoint
libraryURI:(NSString*)libraryURI
initialRoute:(NSString*)initialRoute {
// ...
// 见 [4.1]
[self setupChannels];
// ...
[self maybeSetupPlatformViewChannels];
// ...
}

4.1 setupChannels

engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// FlutterEngine.mm -L367
- (void)setupChannels {
// This will be invoked once the shell is done setting up and the isolate ID
// for the UI isolate is available.
fml::WeakPtr<FlutterEngine> weakSelf = [self getWeakPtr];
// 见 [4.2]
[_binaryMessenger setMessageHandlerOnChannel:@"flutter/isolate"
binaryMessageHandler:^(NSData* message, FlutterBinaryReply reply) {
if (weakSelf) {
weakSelf.get().isolateId =
[[FlutterStringCodec sharedInstance] decode:message];
}
}];
// ...
}

设置 flutter/isolate channel。

4.1.1 FlutterBinaryMessengerRelay 初始化

1
2
3
4
5
6
7
8
9
// FlutterEngine.mm -L132
- (instancetype)initWithName:(NSString*)labelPrefix
project:(FlutterDartProject*)project
allowHeadlessExecution:(BOOL)allowHeadlessExecution {
// ...
// 将当前 FlutterEngine 对象赋值给 FlutterBinaryMessengerRelay 对象 _binaryMessenger 的 parent 成员变量。
_binaryMessenger = [[FlutterBinaryMessengerRelay alloc] initWithParent:self];
// ...
}

4.2 setMessageHandlerOnChannel

engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelay.mm

1
2
3
4
5
6
7
8
9
10
11
12
// FlutterBinaryMessengerRelay.mm -L42
- (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(NSString*)channel
binaryMessageHandler:
(FlutterBinaryMessageHandler)handler {
if (self.parent) {
// 见 [4.3]
return [self.parent setMessageHandlerOnChannel:channel binaryMessageHandler:handler];
} else {
FML_LOG(WARNING) << "Communicating on a dead channel.";
return -1;
}
}

4.3 setMessageHandlerOnChannel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// FlutterEngine.mm -L730
- (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(NSString*)channel
binaryMessageHandler:
(FlutterBinaryMessageHandler)handler {
NSParameterAssert(channel);
if (_shell && _shell->IsSetup()) {
// 见 [4.4]
self.iosPlatformView->GetPlatformMessageRouter().SetMessageHandler(channel.UTF8String, handler);
return _connections->AquireConnection(channel.UTF8String);
} else {
NSAssert(!handler, @"Setting a message handler before the FlutterEngine has been run.");
// Setting a handler to nil for a not setup channel is a noop.
return flutter::ConnectionCollection::MakeErrorConnection(-1);
}
}

4.4 PlatformMessageRouter::SetMessageHandler

1
2
3
4
5
6
7
8
9
// platform_message_router.mm -L43
void PlatformMessageRouter::SetMessageHandler(const std::string& channel,
FlutterBinaryMessageHandler handler) {
message_handlers_.erase(channel);
if (handler) {
message_handlers_[channel] =
fml::ScopedBlock<FlutterBinaryMessageHandler>{handler, fml::OwnershipPolicy::Retain};
}
}

5. native 层

现在来看下 native 层的 Objective-C 的代码,来自 [1.1] 节。

5.1 FlutterMethodChannel 初始化

engine/src/flutter/shell/platform/darwin/common/framework/Source/FlutterChannels.mm

1
2
3
4
5
6
7
8
// FlutterChannels.mm -L181
+ (instancetype)methodChannelWithName:(NSString*)name
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
// 见 [5.1.1]
NSObject<FlutterMethodCodec>* codec = [FlutterStandardMethodCodec sharedInstance];
// 创建 FlutterMethodChannel 对象
return [FlutterMethodChannel methodChannelWithName:name binaryMessenger:messenger codec:codec];
}

该方法注意功能

  1. 入参
    1. name: channel 名
    2. messenger: (FlutterViewController *)controller.binaryMessenger // 也就是 [4.1.1] 里面的对象
  2. 创建 FlutterMethodChannel 对象,后面调用它的 setMethodCallHandler 来处理 Dart 层的调用方法 // 见 [5.2]

5.1.1 FlutterStandardMethodCodec

engine/src/flutter/shell/platform/darwin/common/framework/Source/FlutterStandardCodec.mm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// FlutterStandardCodec.mm -L60
@implementation FlutterStandardMethodCodec {
FlutterStandardReaderWriter* _readerWriter;
}
+ (instancetype)sharedInstance {
static id _sharedInstance = nil;
if (!_sharedInstance) {
// 见 [5.1.2]
FlutterStandardReaderWriter* readerWriter =
[[[FlutterStandardReaderWriter alloc] init] autorelease];
_sharedInstance = [[FlutterStandardMethodCodec alloc] initWithReaderWriter:readerWriter];
}
return _sharedInstance;
}

5.1.2 FlutterMessageCodec

engine/src/flutter/shell/platform/darwin/common/framework/Headers/FlutterCodecs.h

1
2
3
4
5
6
7
8
9
10
11
12
/**
* A factory of compatible reader/writer instances using the Flutter standard
* binary encoding or extensions thereof.
*/
FLUTTER_EXPORT
@interface FlutterStandardReaderWriter : NSObject

/**
* A message encoding/decoding mechanism.
*/
FLUTTER_EXPORT
@protocol FlutterMessageCodec

上面的注释 A message encoding/decoding mechanism. 跟 [2.2] 是一样的,所以 FlutterCodecs 文件中的相关编解码类是跟 Dart 层是相对应的(Dart 层中 ByteData8 对应 iOS 中的 NSData)。

5.2 setMethodCallHandler 方法

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
// FlutterChannels.mm -L231
- (void)setMethodCallHandler:(FlutterMethodCallHandler)handler {
if (!handler) {
if (_connection > 0) {
[_messenger cleanupConnection:_connection];
_connection = 0;
} else {
[_messenger setMessageHandlerOnChannel:_name binaryMessageHandler:nil];
}
return;
}
// Make sure the block captures the codec, not self.
NSObject<FlutterMethodCodec>* codec = _codec;
// 见 [5.3], 这里 messageHandler 就是 [3.6] 中的 handler 。
FlutterBinaryMessageHandler messageHandler = ^(NSData* message, FlutterBinaryReply callback) {
// 见 [5.3.1]
FlutterMethodCall* call = [codec decodeMethodCall:message];
// 见 [5.4]
handler(call, ^(id result) {
if (result == FlutterMethodNotImplemented)
callback(nil);
else if ([result isKindOfClass:[FlutterError class]])
// 见 [5.3.2]
callback([codec encodeErrorEnvelope:(FlutterError*)result]);
else
// 见 [5.3.3]
callback([codec encodeSuccessEnvelope:result]);
});
};
// 见 [4.2]
_connection = [_messenger setMessageHandlerOnChannel:_name binaryMessageHandler:messageHandler];
}

5.3 messageHandler

由前面 [3.6] 可知,根据 channel 名(samples.flutter.dev/battery) 找到 FlutterBinaryMessageHandler 回调后,就会调用它,里面就是 NSData 和 FlutterMethodCall 的相互转换,见 [5.3.1 ~ 5.3.3] 小节。

5.3.1 decodeMethodCall

由 [5.1.1] 可知,在 FlutterStandardMethodCodec 中。

1
2
3
4
5
6
7
8
9
// FlutterStandardCodec.mm -L115
- (FlutterMethodCall*)decodeMethodCall:(NSData*)message {
FlutterStandardReader* reader = [_readerWriter readerWithData:message];
id value1 = [reader readValue];
id value2 = [reader readValue];
NSAssert(![reader hasMore], @"Corrupted standard method call");
NSAssert([value1 isKindOfClass:[NSString class]], @"Corrupted standard method call");
return [FlutterMethodCall methodCallWithMethodName:value1 arguments:value2];
}

将消息读出来,然后封装成 FlutterMethodCall 对象。

5.3.2 encodeErrorEnvelope

1
2
3
4
5
6
7
8
9
10
// FlutterStandardCodec.mm -L105
- (NSData*)encodeErrorEnvelope:(FlutterError*)error {
NSMutableData* data = [NSMutableData dataWithCapacity:32];
FlutterStandardWriter* writer = [_readerWriter writerWithData:data];
[writer writeByte:1];
[writer writeValue:error.code];
[writer writeValue:error.message];
[writer writeValue:error.details];
return data;
}

将 Error 组装成二进制数据。

5.3.3 encodeSuccessEnvelope

1
2
3
4
5
6
7
8
// FlutterStandardCodec.mm -L97
- (NSData*)encodeSuccessEnvelope:(id)result {
NSMutableData* data = [NSMutableData dataWithCapacity:32];
FlutterStandardWriter* writer = [_readerWriter writerWithData:data];
[writer writeByte:0];
[writer writeValue:result];
return data;
}

将成功数据组装成二进制数据。

5.4 setMethodCallHandler 回调

这里以 [1.1] 为例,就是获取当前电量值,然后回调 result,在通过 [5.3.3] 或 [5.3.4] 转成 NSData 后,作为入参给 Complete 调用(见[6.1])。

6. 回传结果

6.1 PlatformMessageResponseDart::Complete

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// platform_message_response_dart.cc -L30
void PlatformMessageResponseDart::Complete(std::unique_ptr<fml::Mapping> data) {
if (callback_.is_empty()) {
return;
}
FML_DCHECK(!is_complete_);
is_complete_ = true;
// 在 UI 线程中执行任务
ui_task_runner_->PostTask(fml::MakeCopyable(
[callback = std::move(callback_), data = std::move(data)]() mutable {
// callback_ 见 [3.1.1] 的赋初始值
std::shared_ptr<tonic::DartState> dart_state =
callback.dart_state().lock();
if (!dart_state) {
return;
}
tonic::DartState::Scope scope(dart_state);
// 见 [6.2]
Dart_Handle byte_buffer =
tonic::DartByteData::Create(data->GetMapping(), data->GetSize());
// 见 [6.3]
tonic::DartInvoke(callback.Release(), {byte_buffer});
}));
}

6.2 DartByteData::Create

engine/src/flutter/third_party/tonic/typed_data/dart_byte_data.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
Dart_Handle DartByteData::Create(const void* data, size_t length) {
if (length < kExternalSizeThreshold) {
auto handle = DartByteData{data, length}.dart_handle();
// The destructor should release the typed data.
return handle;
} else {
void* buf = ::malloc(length);
TONIC_DCHECK(buf);
::memcpy(buf, data, length);
return Dart_NewExternalTypedDataWithFinalizer(
Dart_TypedData_kByteData, buf, length, buf, length, FreeFinalizer);
}
}

将 [5.4.3] 或 [5.4.4] 返回的 NSData 转成 Dart 层的 Data 类型。

6.3 DartInvoke

engine/src/flutter/third_party/tonic/logging/dart_invoke.cc

1
2
3
4
5
6
7
8
9
Dart_Handle DartInvoke(Dart_Handle closure,
std::initializer_list<Dart_Handle> args) {
int argc = args.size();
Dart_Handle* argv = const_cast<Dart_Handle*>(args.begin());
// 见 [6.4]
Dart_Handle handle = Dart_InvokeClosure(closure, argc, argv);
LogIfError(handle);
return handle;
}

6.4 Dart_InvokeClosure

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
DART_EXPORT Dart_Handle Dart_InvokeClosure(Dart_Handle closure,
int number_of_arguments,
Dart_Handle* arguments) {
DARTSCOPE(Thread::Current());
API_TIMELINE_DURATION(T);
CHECK_CALLBACK_STATE(T);
const Instance& closure_obj = Api::UnwrapInstanceHandle(Z, closure);
if (closure_obj.IsNull() || !closure_obj.IsCallable(NULL)) {
RETURN_TYPE_ERROR(Z, closure, Instance);
}
if (number_of_arguments < 0) {
return Api::NewError(
"%s expects argument 'number_of_arguments' to be non-negative.",
CURRENT_FUNC);
}

// Set up arguments to include the closure as the first argument.
const Array& args = Array::Handle(Z, Array::New(number_of_arguments + 1));
Object& obj = Object::Handle(Z);
args.SetAt(0, closure_obj);
for (int i = 0; i < number_of_arguments; i++) {
obj = Api::UnwrapHandle(arguments[i]);
if (!obj.IsNull() && !obj.IsInstance()) {
RETURN_TYPE_ERROR(Z, arguments[i], Instance);
}
args.SetAt(i + 1, obj);
}
// Now try to invoke the closure.
return Api::NewHandle(T, DartEntry::InvokeClosure(args));
}

执行 Closure 的回调,也就是前面 [3.1] 的 callback, 详见 [3.1.1] 的描述,最终会调用到 [2.4.1] 的回调,也就是 [2.4.3] 中的方法。

6.5 _asyncComplete

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// future_impl.dart -L540
void _asyncComplete(FutureOr<T> value) {
assert(!_isComplete);
// Two corner cases if the value is a future:
// 1. the future is already completed and an error.
// 2. the future is not yet completed but might become an error.
// The first case means that we must not immediately complete the Future,
// as our code would immediately start propagating the error without
// giving the time to install error-handlers.
// However the second case requires us to deal with the value immediately.
// Otherwise the value could complete with an error and report an
// unhandled error, even though we know we are already going to listen to
// it.

if (value is Future<T>) {
_chainFuture(value);
return;
}
// TODO(40014): Remove cast when type promotion works.
// This would normally be `as T` but we use `as dynamic` to make the
// unneeded check be implict to match dart2js unsound optimizations in the
// user code.
_asyncCompleteWithValue(value as dynamic); // Value promoted to T.
}

这里的 value 就是 [6.1] 的入参 data, 就是 [1.1] setMethodCallHandler 后回调的值,通过 Complete 异步调用后,最终会调用到 [6.6].

6.6 decodeEnvelope

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// message_codecs.dart -L570
dynamic decodeEnvelope(ByteData envelope) {
// First byte is zero in success case, and non-zero otherwise.
if (envelope.lengthInBytes == 0)
throw const FormatException('Expected envelope, got nothing');
// 创建 ReadBuffer 对象
final ReadBuffer buffer = ReadBuffer(envelope);
if (buffer.getUint8() == 0)
// 见 [6.6.1]
return messageCodec.readValue(buffer);
final dynamic errorCode = messageCodec.readValue(buffer);
final dynamic errorMessage = messageCodec.readValue(buffer);
final dynamic errorDetails = messageCodec.readValue(buffer);
final String? errorStacktrace = (buffer.hasRemaining) ? messageCodec.readValue(buffer) as String : null;
if (errorCode is String && (errorMessage == null || errorMessage is String) && !buffer.hasRemaining)
throw PlatformException(code: errorCode, message: errorMessage as String, details: errorDetails, stacktrace: errorStacktrace);
else
throw const FormatException('Invalid envelope');
}

6.6.1 readValue

1
2
3
4
5
6
7
dynamic readValue(ReadBuffer buffer) {
if (!buffer.hasRemaining)
throw const FormatException('Message corrupted');
final int type = buffer.getUint8();
// 转成 await 调用处需要的数据类型
return readValueOfType(type, buffer);
}

7. native -> dart

前面讲的是 dart 层异步调用 native 层,现在来讲下 native -> dart 的大致逻辑,代码来自我们项目中的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (void)test {
// 见 [7.1]
[_channel invokeMethod:@"didBeforeLoadRequest" arguments:urlStr result:^(id _Nullable result) {
if ([result isKindOfClass:[NSNumber class]]) {
if ([result boolValue]) {
decisionHandler(WKNavigationActionPolicyAllow);
} else {
decisionHandler(WKNavigationActionPolicyCancel);
}
} else {
decisionHandler(WKNavigationActionPolicyAllow);
}
}];
}

7.1 invokeMethod:arguments:result:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// FlutterChannels.mm -L219
- (void)invokeMethod:(NSString*)method arguments:(id)arguments result:(FlutterResult)callback {
// 初始化 FlutterMethodCall
FlutterMethodCall* methodCall = [FlutterMethodCall methodCallWithMethodName:method
arguments:arguments];
// 将 FlutterMethodCall 编码成 NSData
NSData* message = [_codec encodeMethodCall:methodCall];
// 回调操作
FlutterBinaryReply reply = ^(NSData* data) {
if (callback) {
callback((data == nil) ? FlutterMethodNotImplemented : [_codec decodeEnvelope:data]);
}
};
// 见 [7.2.1]
[_messenger sendOnChannel:_name message:message binaryReply:reply];
}

该方法主要功能:

  1. 创建 FlutterMethodCall 对象,跟 [2.3] 是类似的
  2. FlutterMethodCall 对象进行编码操作
  3. reply: 对 dart 层返回的数据进行解码操作,并执行 callback 回调

7.2.1 sendOnChannel:message:

1
2
3
4
5
6
7
8
9
10
11
// FlutterBinaryMessengerRelay.mm -L28
- (void)sendOnChannel:(NSString*)channel
message:(NSData*)message
binaryReply:(FlutterBinaryReply)callback {
if (self.parent) {
// 见 [7.2.2]
[self.parent sendOnChannel:channel message:message binaryReply:callback];
} else {
FML_LOG(WARNING) << "Communicating on a dead channel.";
}
}

7.2.2 sendOnChannel:message:binaryReply:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// FlutterEngine.mm -L704
- (void)sendOnChannel:(NSString*)channel
message:(NSData*)message
binaryReply:(FlutterBinaryReply)callback {
NSParameterAssert(channel);
NSAssert(_shell && _shell->IsSetup(),
@"Sending a message before the FlutterEngine has been run.");
// 创建 PlatformMessageResponseDarwin 对象,后续在 Platform 线程中执行任务,见 [7.2.3]
fml::RefPtr<flutter::PlatformMessageResponseDarwin> response =
(callback == nil) ? nullptr
: fml::MakeRefCounted<flutter::PlatformMessageResponseDarwin>(
^(NSData* reply) {
callback(reply);
},
_shell->GetTaskRunners().GetPlatformTaskRunner());
// 创建 PlatformMessage 对象,跟 [3.1.3] 是类似的
fml::RefPtr<flutter::PlatformMessage> platformMessage =
(message == nil) ? fml::MakeRefCounted<flutter::PlatformMessage>(channel.UTF8String, response)
: fml::MakeRefCounted<flutter::PlatformMessage>(
channel.UTF8String, flutter::GetVectorFromNSData(message), response);
// 见 [7.3]
_shell->GetPlatformView()->DispatchPlatformMessage(platformMessage);
}

7.2.3 PlatformMessageResponseDarwin

1
2
3
4
5
6
// platform_message_response_darwin.mm -L9
PlatformMessageResponseDarwin::PlatformMessageResponseDarwin(
PlatformMessageResponseCallback callback,
fml::RefPtr<fml::TaskRunner> platform_task_runner)
: callback_(callback, fml::OwnershipPolicy::Retain),
platform_task_runner_(std::move(platform_task_runner)) {}

7.3.4 PlatformMessageResponseDarwin::Complete

1
2
3
4
5
6
7
8
// platform_message_response_darwin.mm -L17
void PlatformMessageResponseDarwin::Complete(std::unique_ptr<fml::Mapping> data) {
fml::RefPtr<PlatformMessageResponseDarwin> self(this);
// 在 platform 线程中执行任务
platform_task_runner_->PostTask(fml::MakeCopyable([self, data = std::move(data)]() mutable {
self->callback_.get()(GetNSDataFromMapping(std::move(data)));
}));
}

这里的 callback_ 就是 [7.2.2] 里面的

1
2
3
^(NSData* reply) {
callback(reply);
},

从而 callback 回调到 [7.1] 的 reply,最终会将调用到 [7] 的 result 回调,自此,整个链路就完成了。

7.3 PlatformView::DispatchPlatformMessage

1
2
3
4
5
6
// platform_view.cc -L35
void PlatformView::DispatchPlatformMessage(
fml::RefPtr<PlatformMessage> message) {
// 见 [7.4]
delegate_.OnPlatformViewDispatchPlatformMessage(std::move(message));
}

这里 PlatformView 是前面 PlatformViewIOS 的父类,所以看下 PlatformViewIOS 的初始化方法,看 delegate_.

7.3.1 PlatformViewIOS 初始化

1
2
3
4
5
6
7
// platform_view_ios.mm -47
PlatformViewIOS::PlatformViewIOS(PlatformView::Delegate& delegate,
IOSRenderingAPI rendering_api,
flutter::TaskRunners task_runners)
: PlatformView(delegate, std::move(task_runners)),
ios_context_(IOSContext::Create(rendering_api)),
accessibility_bridge_([this](bool enabled) { PlatformView::SetSemanticsEnabled(enabled); }) {}

由前面 [3.5] 可知,这里的 delegate_ 就是 Shell 对象。

7.4 Shell::OnPlatformViewDispatchPlatformMessage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// shell.cc -L838
// |PlatformView::Delegate|
void Shell::OnPlatformViewDispatchPlatformMessage(
fml::RefPtr<PlatformMessage> message) {
FML_DCHECK(is_setup_);
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());

// 在 UI 线程中执行任务
task_runners_.GetUITaskRunner()->PostTask(
[engine = engine_->GetWeakPtr(), message = std::move(message)] {
if (engine) {
// 见 [7.5]
engine->DispatchPlatformMessage(std::move(message));
}
});
}

7.5 Engine::DispatchPlatformMessage

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
// engine.cc -L333
void Engine::DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message) {
// 判断相关 channel 名,在调用前面 [4.1] setupChannels 方法的时候,会设置这些 channel
std::string channel = message->channel();
if (channel == kLifecycleChannel) {
if (HandleLifecyclePlatformMessage(message.get())) {
return;
}
} else if (channel == kLocalizationChannel) {
if (HandleLocalizationPlatformMessage(message.get())) {
return;
}
} else if (channel == kSettingsChannel) {
HandleSettingsPlatformMessage(message.get());
return;
} else if (!runtime_controller_->IsRootIsolateRunning() &&
channel == kNavigationChannel) {
// If there's no runtime_, we may still need to set the initial route.
HandleNavigationPlatformMessage(std::move(message));
return;
}
// 在主 isolate 中执行任务
if (runtime_controller_->IsRootIsolateRunning() &&
// 见 [7.6]
runtime_controller_->DispatchPlatformMessage(std::move(message))) {
return;
}

FML_DLOG(WARNING) << "Dropping platform message on channel: " << channel;
}

7.6 RuntimeController::DispatchPlatformMessage

1
2
3
4
5
6
7
8
9
10
11
12
bool RuntimeController::DispatchPlatformMessage(
fml::RefPtr<PlatformMessage> message) {
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
TRACE_EVENT1("flutter", "RuntimeController::DispatchPlatformMessage",
"mode", "basic");
// 见 [7.7]
platform_configuration->DispatchPlatformMessage(std::move(message));
return true;
}

return false;
}

7.7 PlatformConfiguration::DispatchPlatformMessage

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
void PlatformConfiguration::DispatchPlatformMessage(
fml::RefPtr<PlatformMessage> message) {
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
if (!dart_state) {
FML_DLOG(WARNING)
<< "Dropping platform message for lack of DartState on channel: "
<< message->channel();
return;
}
tonic::DartState::Scope scope(dart_state);
// message->hasData() 是前面 [7.1] 中的 FlutterMethodCall 对象
Dart_Handle data_handle =
(message->hasData()) ? ToByteData(message->data()) : Dart_Null();
if (Dart_IsError(data_handle)) {
FML_DLOG(WARNING)
<< "Dropping platform message because of a Dart error on channel: "
<< message->channel();
return;
}

int response_id = 0;
// 跟 response_id 和 response 关联起来,由前面 [7.2.2] 可知这里 message->response() 为空
if (auto response = message->response()) {
response_id = next_response_id_++;
pending_responses_[response_id] = response;
}
// native -> dart, 见 [7.8]
tonic::LogIfError(
tonic::DartInvokeField(library_.value(), "_dispatchPlatformMessage",
{tonic::ToDart(message->channel()), data_handle,
tonic::ToDart(response_id)}));
}

7.8 _dispatchPlatformMessage

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
// hooks.dart -L144
@pragma('vm:entry-point')
// ignore: unused_element
void _dispatchPlatformMessage(String name, ByteData? data, int responseId) {
if (name == ChannelBuffers.kControlChannelName) {
try {
channelBuffers.handleMessage(data!);
} catch (ex) {
_printDebug('Message to "$name" caused exception $ex');
} finally {
window._respondToPlatformMessage(responseId, null);
}
} else if (window.onPlatformMessage != null) {
// 见 [7.8.1]
_invoke3<String, ByteData?, PlatformMessageResponseCallback>(
window.onPlatformMessage,
window._onPlatformMessageZone,
name,
data,
(ByteData? responseData) {
window._respondToPlatformMessage(responseId, responseData);
},
);
} else {
channelBuffers.push(name, data, (ByteData? responseData) {
window._respondToPlatformMessage(responseId, responseData);
});
}
}

7.8.1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// hooks.dart -L270
/// Invokes [callback] inside the given [zone] passing it [arg1], [arg2], and [arg3].
void _invoke3<A1, A2, A3>(void callback(A1 a1, A2 a2, A3 a3)?, Zone zone, A1 arg1, A2 arg2, A3 arg3) {
if (callback == null)
return;

assert(zone != null); // ignore: unnecessary_null_comparison

if (identical(zone, Zone.current)) {
callback(arg1, arg2, arg3);
} else {
zone.runGuarded(() {
callback(arg1, arg2, arg3);
});
}
}

在给定的 Zone 里面,根据参数回调 callback.

  • callback: window.onPlatformMessage, 见 [7.9]
  • zone: window._onPlatformMessageZone
  • arg1: name // channel 名
  • arg2: data // FlutterMethodCall 对象,见 [7.7]
  • arg3: window._respondToPlatformMessage, 见 [7.10]

7.9 onPlatformMessage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Listens for platform messages and directs them to the [defaultBinaryMessenger].
mixin ServicesBinding on BindingBase, SchedulerBinding {
@override
void initInstances() {
super.initInstances();
_instance = this;
_defaultBinaryMessenger = createBinaryMessenger();
_restorationManager = createRestorationManager();
// 见 [7.9.1]
window.onPlatformMessage = defaultBinaryMessenger.handlePlatformMessage;
initLicenses();
SystemChannels.system.setMessageHandler((dynamic message) => handleSystemMessage(message as Object));
SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage);
readInitialLifecycleStateFromNativeWindow();
}

7.9.1 handlePlatformMessage

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
Future<void> handlePlatformMessage(
String channel,
ByteData? data,
ui.PlatformMessageResponseCallback? callback,
) async {
ByteData? response;
try {
// 获取 handler, 跟 [3.6] 类似,现在的问题是在哪里设置的 _handlers 呢?见 [7.13]
final MessageHandler? handler = _handlers[channel];
if (handler != null) {
// 执行 handler
response = await handler(data);
} else {
ui.channelBuffers.push(channel, data, callback!);
callback = null;
}
} catch (exception, stack) {
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'services library',
context: ErrorDescription('during a platform message callback'),
));
} finally {
if (callback != null) {
// 回调 response, 见 [7.10]
callback(response);
}
}
}

7.10 _respondToPlatformMessage

1
2
3
4
// window -L1216, 见 [7.11]
/// Called by [_dispatchPlatformMessage].
void _respondToPlatformMessage(int responseId, ByteData? data)
native 'PlatformConfiguration_respondToPlatformMessage';

_dispatchPlatformMessage 会调用 _respondToPlatformMessage 方法,而 _respondToPlatformMessage 又是一个 native 方法。

7.11 _RespondToPlatformMessage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// platform_configuration.cc -L159
void _RespondToPlatformMessage(Dart_NativeArguments args) {
tonic::DartCallStatic(&RespondToPlatformMessage, args);
}

// platform_configuration.cc -L141
void RespondToPlatformMessage(Dart_Handle window,
int response_id,
const tonic::DartByteData& data) {
if (Dart_IsNull(data.dart_handle())) {
UIDartState::Current()
->platform_configuration()
->CompletePlatformMessageEmptyResponse(response_id);
} else {
// TODO(engine): Avoid this copy.
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
// 见 [7.11.1]
UIDartState::Current()
->platform_configuration()
->CompletePlatformMessageResponse(
response_id,
std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()));
}
}

7.11.1 PlatformConfiguration::CompletePlatformMessageResponse

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void PlatformConfiguration::CompletePlatformMessageResponse(
int response_id,
std::vector<uint8_t> data) {
// 这 response_id 为 0, 对应着 [7.1] result 入参为 nil 的情况
if (!response_id) {
return;
}
auto it = pending_responses_.find(response_id);
// 根据 response_id 没找到内容
if (it == pending_responses_.end()) {
return;
}
// 获取 [7.7] 的 message->response(), 对应 [7.2.2] 的 response 对象
auto response = std::move(it->second);
// 移除该回调
pending_responses_.erase(it);
// 见 [7.3.4]
response->Complete(std::make_unique<fml::DataMapping>(std::move(data)));
}

7.12 setMethodCallHandler

1
2
3
4
5
6
7
8
9
10
11
12
// paltform_channel.dart -L377
void setMethodCallHandler(Future<dynamic> Function(MethodCall call)? handler) {
// 见 MethodChannel(this) 和 handler 关联起来
_methodChannelHandlers[this] = handler;
// 见 [7.13]
binaryMessenger.setMessageHandler(
name,
handler == null
? null
: (ByteData? message) => _handleAsMethodCall(message, handler),
);
}

7.13 setMessageHandler

1
2
3
4
5
6
7
8
9
10
// binding.dart -L311
void setMessageHandler(String channel, MessageHandler? handler) {
if (handler == null)
_handlers.remove(channel);
else
_handlers[channel] = handler;
ui.channelBuffers.drain(channel, (ByteData? data, ui.PlatformMessageResponseCallback callback) async {
await handlePlatformMessage(channel, data, callback);
});
}

这里跟前面 [7.9.1] 串联起来了,对 _handlers 进行赋值。

8. 总结

8.1 调用链路

8.1.1 dart -> native

调用流程如下:

赋值 handler 流程图如下:

method channel 的执行涉及到主线程和UI线程的交互,代码调用从 dart -> shell -> native(ios), 执行完成后再原路返回 native(ios) -> shell -> dart.

  • 3.4 Shell::OnEngineHandlePlatformMessage, 在 UI 线程(io.flutter.1.ui), 将任务派发给主线程
  • 6.1 PlatformMessageResponseDart::Complete, 在主线程(platform), 将任务派发给 UI 线程

8.1.2 native -> dart

调用流程如下:

同 [8.1.1], method channel 的执行涉及到主线程和UI线程的交互,代码调用从 native(ios) -> shell -> dart, 执行完成后再原路返回 dart -> shell -> native(ios).

  • 7.3.4 PlatformMessageResponseDarwin::Complete, 在 UI 线程(io.flutter.1.ui), 将任务派发给主线程
  • 7.4 Shell::OnPlatformViewDispatchPlatformMessage, 在主线程(platform), 将任务派发给 UI 线程

8.2 相关概念

  1. shell
  2. isolate(和线程的关系)
  3. ui platform 等线程,flutter 中有多少线程?
  4. future Complete 异步调用
  5. dart 和 native(ios) 中的相关编解码类

8.3 问题

  1. dart 层和 native 层数据通信的本质是什么?
  2. 怎么监控 platform channel 的执行过程,方便调试?

answer

  1. 看源码可知,双方交互都是传递二进制数据,然后通过双方的编解码类来转成当前层所需要的对象,所以是二进制数据流;
  2. 可以自定义一个 BinaryMessenger 类,然后替换系统的 ServicesBinding.defaultBinaryMessenger,从而达到监控的目的;

10. 参考链接

在做今天的每日一题:832. 翻转图像时,看到了之前的笔记,里面提到了一道类似的题目48. 旋转图像,如果没记错的话,它应该是去年的一道每日一题。当时还想着要把沿对角线翻转的代码给记住的,但是现在也不记得了,为了完成去年前的任务,晚上花了点时间把相关翻转代码记录一下。

经验

给定一个 n × n 的二维矩阵 matrix(eg: [[1,2,3],[4,5,6],[7,8,9]]),在遍历中分别输出行下标(i)和列表(j)的值。
以下的代码,记住画个图再来推理一篇,记忆效果会更好。

水平上下翻转

行和是 n-1, 遍历一半;列正常处理。

1
2
3
4
5
6
7
8
9
10
11
for (int i = 0; i < n/2; i++) {
for (int j = 0; j < n; j++) {
swap(matrix[i][j], matrix[n-i-1][j]);
cout << '[' << i << ',' << j << ']'<< endl;
}
}
/*
[0,0]
[0,1]
[0,2]
*/

垂直左右翻转

行正常处理;列和是 n-1, 遍历一半。

1
2
3
4
5
6
7
8
9
10
11
for (int i = 0; i < n; i++) {
for (int j = 0; j < n/2; j++) {
swap(matrix[i][j], matrix[i][n-j-1]);
cout << '[' << i << ',' << j << ']'<< endl;
}
}
/*
[0,0]
[1,0]
[2,0]
*/

主对角线(左上-右下)翻转

交换i, j.

1
2
3
4
5
6
7
8
9
10
11
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
swap(matrix[i][j], matrix[j][i]);
cout << '[' << i << ',' << j << ']'<< endl;
}
}
/*
[1,0]
[2,0]
[2,1]
*/

副对角线(右上-左下)翻转

交换i, j.

1
2
3
4
5
6
7
8
9
10
11
for (int i = 0; i < n-1; i++) {
for(int j = 0; j < n-i-1; j++) {
swap(matrix[i][j], matrix[n-j-1][n-i-1]);
cout << "[" << i << "," << j << "]" << endl;
}
}
/*
[0,0]
[0,1]
[1,0]
*/

套路

  1. 顺时针90度:主对角线(左上-右下)翻转,再垂直左右翻转
  2. 逆时针90度:主对角线(左上-右下)翻转,再水平上下翻转
  3. 顺时针180度:主对角线(左上-右下)翻转,再副对角线(右上-左下)翻转
  4. 逆时针180度:主对角线(左上-右下)翻转,再副对角线(右上-左下)翻转

48. 旋转图像

顺时针旋转 90 度。

用套路1.

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
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int n = matrix.size();
if (!n) return;
// 主对角线翻转
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
myswap(matrix[i][j], matrix[j][i]);
}
}
// 垂直左右翻转
int mid = n >> 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < mid; j++) {
myswap(matrix[i][j], matrix[i][n-j-1]);
}
}
}

void myswap(int& a, int& b) {
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
};

二分查找,就是在一个区间内查找某个值(eg: target)的时候,每次把区间一分为二,然后选择满足性质的区间(即包含 target)继续一分为二,直到区间长度为一。

阅读全文 »

本文是对 Advanced Graphics and Animations for iOS Apps 的一个学习记录文章,字幕在 transcripts ,当然也可以下载 WWDC 在桌面上看带有字幕的视频。这篇挺实用的,讲解了渲染的基本流程,以及怎么发现并解决渲染性能的问题。(ps: 20中旬发现这个视频下架了,可以在 419_hd_advanced_graphics_and_animation_performance.mov 下载)。

阅读全文 »