0%

iOS Flutter Platform Channel

本文基于 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. 参考链接