graph LR
subgraph DartVM
Dart(DartFramework)-->|await|Engine(EngineC++)
end
subgraph Platform
Engine-->|GetPlatformTaskRunner->PostTask|PlatformC++-->PlatformJava
PlatformJava-->PlatformC++
PlatformC++-->|ui_task_runner_->PostTask|Engine-->Dart
end
数据反向也是类似的编解码
graph LR
subgraph Dart
MethodCallDart("MethodCall:StringMethodName,ObjectArguments")-->|encode|ByteBufferDart("ByteDataDart")
end
ByteBufferDart-->Transport-->|decode|MethodCallNative
subgraph native
MethodCallNative
end
graph TB
subgraph DartUiThreadNative
ALooper_pollOnce-->MessageLoopAndroid::OnEventFired
-->Engine::DispatchPlatformMessage-->RuntimeController::DispatchPlatformMessage
-->PlatformConfiguration::DispatchPlatformMessage-->tonic::DartInvoke
end
subgraph DartUiThreadDart
tonic::DartInvoke-->binding.dart-->platform_channel.dart-->callHandler
end
classDiagram
class MethodChannel {
String name
MethodCodec codec
BinaryMessenger binaryMessenger
}
class MethodCodec {
encodeMethodCall(MethodCall methodCall)ByteData
decodeMethodCall(ByteData? methodCall)MethodCall
decodeEnvelope(ByteData envelope)dynamic
encodeSuccessEnvelope(dynamic result)ByteData
encodeErrorEnvelope(String code, String? message, dynamic details)ByteData
}
class BinaryMessenger{
handlePlatformMessage(String channel, ByteData? data, ui.PlatformMessageResponseCallback? callback)Future~void~
send(String channel, ByteData? message)Future~ByteData~
setMessageHandler(String channel, MessageHandler? handler)void
}
MethodCodec<|--StandardMethodCodec
MethodCodec<|--JSONMethodCodec
BinaryMessenger<|--_DefaultBinaryMessenger
classDiagram
class BasicMessageChannel~T~{
String name
MessageCodec<T> codec
BinaryMessenger binaryMessenger
}
class MessageCodec~T~ {
encodeMessage(T message)ByteData
decodeMessage(ByteData? message) T
}
MethodChannel和MessageChannel的区别: codec结构不同,Message不涉及MethodCall结构,并且request参数和response都是类型T。
class MainActivity() : FlutterActivity() {
private val CHANNEL = "samples.flutter.dev/battery"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
MethodChannel(flutterView, CHANNEL).setMethodCallHandler { call, result ->
// Note: this method is invoked on the main thread.
if (call.method == "getBatteryLevel") {
val batteryLevel = getBatteryLevel()//android平台api调用获取
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error("UNAVAILABLE", "Battery level not available.", null)
}
} else {
result.notImplemented()
}
}
MethodChannel.java
private final BinaryMessenger messenger;
public MethodChannel(BinaryMessenger messenger, String name) {
this(messenger, name, StandardMethodCodec.INSTANCE);
}
public MethodChannel(BinaryMessenger messenger, String name, MethodCodec codec) {
this.messenger = messenger;
this.name = name;
this.codec = codec;
}
@UiThread
public void setMethodCallHandler(@Nullable MethodChannel.MethodCallHandler handler) {
this.messenger.setMessageHandler(this.name, handler == null ? null : new MethodChannel.IncomingMethodCallHandler(handler));
}
interface BinaryMessenger
@UiThread
void setMessageHandler(@NonNull String var1, @Nullable BinaryMessenger.BinaryMessageHandler var2);
FlutterView extends SurfaceView implements BinaryMessenger, TextureRegistry {
@UiThread
public void setMessageHandler(String channel, BinaryMessageHandler handler) {
this.mNativeView.setMessageHandler(channel, handler);
}
}
FlutterNativeView implements BinaryMessenger
@UiThread
public void setMessageHandler(String channel, BinaryMessageHandler handler) {
this.dartExecutor.setMessageHandler(channel, handler);
}
DartExecutor implements BinaryMessenger
@NonNull
private final DartMessenger messenger;
@UiThread
public void setMessageHandler(@NonNull String channel, @Nullable BinaryMessageHandler handler) {
this.messenger.setMessageHandler(channel, handler);
}
DartMessenger
//platform注册监听
public void setMessageHandler(@NonNull String channel, @Nullable BinaryMessageHandler handler) {
if (handler == null) {
Log.v("DartMessenger", "Removing handler for channel '" + channel + "'");
this.messageHandlers.remove(channel);
} else {
Log.v("DartMessenger", "Setting handler for channel '" + channel + "'");
this.messageHandlers.put(channel, handler);
}
}
private final class IncomingMethodCallHandler implements BinaryMessageHandler {
private final MethodChannel.MethodCallHandler handler;
IncomingMethodCallHandler(MethodChannel.MethodCallHandler handler) {
this.handler = handler;
}
@UiThread
public void onMessage(ByteBuffer message, final BinaryReply reply) {
MethodCall call = MethodChannel.this.codec.decodeMethodCall(message);//ByteBuffer to Object
try {
this.handler.onMethodCall(call, new MethodChannel.Result() {
public void success(Object result) {
reply.reply(MethodChannel.this.codec.encodeSuccessEnvelope(result));//object to ByteBuffer
}
public void error(String errorCode, String errorMessage, Object errorDetails) {
reply.reply(MethodChannel.this.codec.encodeErrorEnvelope(errorCode, errorMessage, errorDetails));
}
public void notImplemented() {
reply.reply((ByteBuffer)null);
}
});
} catch (RuntimeException var5) {
Log.e("MethodChannel#" + MethodChannel.this.name, "Failed to handle method call", var5);
reply.reply(MethodChannel.this.codec.encodeErrorEnvelope("error", var5.getMessage(), (Object)null));
}
static const platform = const MethodChannel('samples.flutter.dev/battery');
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}'.";
}
const MethodChannel(this.name, [this.codec = const StandardMethodCodec(), this.binaryMessenger = defaultBinaryMessenger ])
/// The logical channel on which communication happens, not null.
final String name;
/// The message codec used by this channel, not null.
final MethodCodec codec;
/// The messenger used by this channel to send platform messages.
///
/// The messenger may not be null.
final BinaryMessenger binaryMessenger;
/// The default instance of [BinaryMessenger].
///
/// This is used to send messages from the application to the platform, and
/// keeps track of which handlers have been registered on each channel so
/// it may dispatch incoming messages to the registered handler.
const BinaryMessenger defaultBinaryMessenger = _DefaultBinaryMessenger._();
@optionalTypeArgs
Future<T> invokeMethod<T>(String method, [ dynamic arguments ]) async {
final ByteData result = await binaryMessenger.send(
name,
codec.encodeMethodCall(MethodCall(method, arguments)),
);
final T typedResult = codec.decodeEnvelope(result);
return typedResult;
/// A messenger which sends binary data across the Flutter platform barrier.
///
/// This class also registers handlers for incoming messages.*
BinaryMessenger
/// Send a binary message to the platform plugins on the given channel.
/// Returns a [Future] which completes to the received response, undecoded,
/// in binary form.
Future<ByteData> send(String channel, ByteData message);
_DefaultBinaryMessenger
/// A function which takes a platform message and asynchronously returns an encoded response.
typedef MessageHandler = Future<ByteData> Function(ByteData message);
// Mock handlers that intercept and respond to outgoing messages.
// This is static so that this class can have a const constructor.
static final Map<String, MessageHandler> _mockHandlers = <String, MessageHandler>{};
@override
Future<ByteData> send(String channel, ByteData message) {
final MessageHandler handler = _mockHandlers[channel];
if (handler != null)
return handler(message);
return _sendPlatformMessage(channel, message);
}
Future<ByteData> _sendPlatformMessage(String channel, ByteData message) {
final Completer<ByteData> completer = Completer<ByteData>();
ui.window.sendPlatformMessage(channel, message, (ByteData reply) {
try {
completer.complete(reply);
}
return completer.future;
Window
/// Sends a message to a platform-specific plugin.
///
/// The `name` parameter determines which plugin receives the message. The
/// `data` parameter contains the message payload and is typically UTF-8
/// encoded JSON but can be arbitrary data. If the plugin replies to the
/// message, `callback` will be called with the response.
void sendPlatformMessage(String name,
ByteData data,
PlatformMessageResponseCallback callback) {
final String error =
_sendPlatformMessage(name, _zonedPlatformMessageResponseCallback(callback), data);
if (error != null)
throw Exception(error);
String _sendPlatformMessage(String name,
PlatformMessageResponseCallback callback,
ByteData data) native 'Window_sendPlatformMessage';
Window.cc
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register({
{"Window_sendPlatformMessage", _SendPlatformMessage, 4, true},
void _SendPlatformMessage(Dart_NativeArguments args) {
tonic::DartCallStatic(&SendPlatformMessage, args);
}
Dart_Handle SendPlatformMessage(Dart_Handle window,
const std::string& name,
Dart_Handle callback,
Dart_Handle data_handle) {
dart_state->window()->client()->HandlePlatformMessage
return Dart_Null();
Engine
void Engine::HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) {
if (message->channel() == kAssetChannel) {
HandleAssetPlatformMessage(std::move(message));
} else {
delegate_.OnEngineHandlePlatformMessage(std::move(message));
}
}
class Delegate {
//--------------------------------------------------------------------------
/// @brief When the Flutter application has a message to send to the
/// underlying platform, the message needs to be forwarded to
/// the platform on the the appropriate thread (via the platform
/// task runner). The engine delegates this task to the shell
/// via this method.
///
/// @see `PlatformView::HandlePlatformMessage`
///
/// @param[in] message The message from the Flutter application to send to
/// the underlying platform.
///
virtual void OnEngineHandlePlatformMessage(
fml::RefPtr<PlatformMessage> message) = 0;
Shell
const TaskRunners task_runners_;
const TaskRunners& Shell::GetTaskRunners() const {return task_runners_;}
Shell::Shell(DartVMRef vm, TaskRunners task_runners, Settings settings)
: task_runners_(std::move(task_runners)),
// |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;
}
task_runners_.GetPlatformTaskRunner()->PostTask(
[view = platform_view_->GetWeakPtr(), message = std::move(message)]() {
if (view) {
view->HandlePlatformMessage(std::move(message));
}
});
}
void PlatformView::HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) {
if (auto response = message->response())
response->CompleteEmpty();
}
// |PlatformView|
void PlatformViewAndroid::HandlePlatformMessage(
FlutterViewHandlePlatformMessage(env, view.obj(), java_channel.obj(),
message_array.obj(), response_id);
shell\platform\android\platform_view_android_jni.cc
bool PlatformViewAndroid::Register(JNIEnv* env) {
g_flutter_jni_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass("io/flutter/embedding/engine/FlutterJNI"));
if (g_flutter_jni_class->is_null()) {
FML_LOG(ERROR) << "Failed to find FlutterJNI Class.";
return false;
}
g_handle_platform_message_method =
env->GetMethodID(g_flutter_jni_class->obj(), "handlePlatformMessage",
"(Ljava/lang/String;[BI)V");
static jmethodID g_handle_platform_message_method = nullptr;
void FlutterViewHandlePlatformMessage(JNIEnv* env,
jobject obj,
jstring channel,
jobject message,
jint responseId) {
env->CallVoidMethod(obj, g_handle_platform_message_method, channel, message,
responseId);
FML_CHECK(CheckException(env));
}
FlutterJNI
// Called by native.
private void handlePlatformMessage(@NonNull String channel, byte[] message, int replyId) {
if (this.platformMessageHandler != null) {
this.platformMessageHandler.handleMessageFromDart(channel, message, replyId);
}
}
PlatformMessageHandler
void handleMessageFromDart(@NonNull String var1, @Nullable byte[] var2, int var3);
void handlePlatformMessageResponse(int var1, @Nullable byte[] var2);
@NonNull
private final Map<String, BinaryMessageHandler> messageHandlers;
//由dart发起调用
public void handleMessageFromDart(@NonNull String channel, @Nullable byte[] message, int replyId) {
Log.v("DartMessenger", "Received message from Dart over channel '" + channel + "'");
BinaryMessageHandler handler = (BinaryMessageHandler)this.messageHandlers.get(channel);
if (handler != null) {
try {
Log.v("DartMessenger", "Deferring to registered handler to process message.");
ByteBuffer buffer = message == null ? null : ByteBuffer.wrap(message);
handler.onMessage(buffer, new DartMessenger.Reply(this.flutterJNI, replyId));
} catch (Exception var6) {
Log.e("DartMessenger", "Uncaught exception in binary message listener", var6);
this.flutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
}
} else {
Log.v("DartMessenger", "No registered handler for message. Responding to Dart with empty reply message.");
this.flutterJNI.invokePlatformMessageEmptyResponseCallback(replyId);
}
}
DartMessenger
private static class Reply implements BinaryReply {
@NonNull
private final FlutterJNI flutterJNI;
private final int replyId;
private final AtomicBoolean done = new AtomicBoolean(false);
Reply(@NonNull FlutterJNI flutterJNI, int replyId) {
this.flutterJNI = flutterJNI;
this.replyId = replyId;
}
public void reply(@Nullable ByteBuffer reply) {
if (this.done.getAndSet(true)) {
throw new IllegalStateException("Reply already submitted");
} else {
if (reply == null) {
this.flutterJNI.invokePlatformMessageEmptyResponseCallback(this.replyId);
} else {
this.flutterJNI.invokePlatformMessageResponseCallback(this.replyId, reply, reply.position());
}
FlutterJNI
@UiThread
public void invokePlatformMessageResponseCallback(int responseId, @Nullable ByteBuffer message, int position) {
this.ensureRunningOnMainThread();
if (this.isAttached()) {
this.nativeInvokePlatformMessageResponseCallback(this.nativePlatformViewId, responseId, message, position);
} else {
Log.w("FlutterJNI", "Tried to send a platform message response, but FlutterJNI was detached from native C++. Could not send. Response ID: " + responseId);
}
private native void nativeInvokePlatformMessageResponseCallback(long var1, int var3, @Nullable ByteBuffer var4, int var5);
shell\platform\android\platform_view_android_jni.cc
bool RegisterApi(JNIEnv* env) {
static const JNINativeMethod flutter_jni_methods[] = {
// Start of methods from FlutterJNI
{
.name = "nativeInvokePlatformMessageResponseCallback",
.signature = "(JILjava/nio/ByteBuffer;I)V",
.fnPtr =
reinterpret_cast<void*>(&InvokePlatformMessageResponseCallback),
},
static void InvokePlatformMessageResponseCallback(JNIEnv* env,
jobject jcaller,
jlong shell_holder,
jint responseId,
jobject message,
jint position) {
ANDROID_SHELL_HOLDER->GetPlatformView()
->InvokePlatformMessageResponseCallback(env, //
responseId, //
message, //
position //
);
}
void PlatformViewAndroid::InvokePlatformMessageResponseCallback(
JNIEnv* env,
jint response_id,
jobject java_response_data,
jint java_response_position) {
if (!response_id)
return;
auto it = pending_responses_.find(response_id);
if (it == pending_responses_.end())
return;
uint8_t* response_data =
static_cast<uint8_t*>(env->GetDirectBufferAddress(java_response_data));
std::vector<uint8_t> response = std::vector<uint8_t>(
response_data, response_data + java_response_position);
auto message_response = std::move(it->second);
pending_responses_.erase(it);
message_response->Complete(
std::make_unique<fml::DataMapping>(std::move(response)));
}
void PlatformMessageResponseDart::Complete(std::unique_ptr<fml::Mapping> data) {
if (callback_.is_empty())
return;
FML_DCHECK(!is_complete_);
is_complete_ = true;
ui_task_runner_->PostTask(fml::MakeCopyable(
[callback = std::move(callback_), data = std::move(data)]() mutable {
std::shared_ptr<tonic::DartState> dart_state =
callback.dart_state().lock();
if (!dart_state)
return;
tonic::DartState::Scope scope(dart_state);
Dart_Handle byte_buffer = WrapByteData(std::move(data));
tonic::DartInvoke(callback.Release(), {byte_buffer});//调用SendPlatformMessage的第三个参数闭包
}));
}
ByteBuffer encodeMethodCall(MethodCall methodCall);
MethodCall decodeMethodCall(ByteBuffer methodCall);
ByteBuffer encodeSuccessEnvelope(Object result);
Object decodeEnvelope(ByteBuffer envelope);
StandardMethodCodec
@Override
public MethodCall decodeMethodCall(ByteBuffer methodCall) {
methodCall.order(ByteOrder.nativeOrder());
final Object method = messageCodec.readValue(methodCall);
final Object arguments = messageCodec.readValue(methodCall);
if (method instanceof String && !methodCall.hasRemaining()) {
return new MethodCall((String) method, arguments);
}
throw new IllegalArgumentException("Method call corrupted");
}
@Override
public ByteBuffer encodeSuccessEnvelope(Object result) {
final ExposedByteArrayOutputStream stream = new ExposedByteArrayOutputStream();
stream.write(0);
messageCodec.writeValue(stream, result);
final ByteBuffer buffer = ByteBuffer.allocateDirect(stream.size());
buffer.put(stream.buffer(), 0, stream.size());
return buffer;
}
shell/platform/android/platform_view_android_jni_impl.cc
static void DispatchPlatformMessage(JNIEnv* env,
jobject jcaller,
jlong shell_holder,
jstring channel,
jobject message,
jint position,
jint responseId) {
ANDROID_SHELL_HOLDER->GetPlatformView()->DispatchPlatformMessage(
env, //
fml::jni::JavaStringToString(env, channel), //
message, //
position, //
responseId //
);
}
shell/platform/android/platform_view_android.cc
void PlatformViewAndroid::DispatchPlatformMessage(JNIEnv* env,
std::string name,
jobject java_message_data,
jint java_message_position,
jint response_id) {
uint8_t* message_data =
static_cast<uint8_t*>(env->GetDirectBufferAddress(java_message_data));
fml::MallocMapping message =
fml::MallocMapping::Copy(message_data, java_message_position);
fml::RefPtr<flutter::PlatformMessageResponse> response;
if (response_id) {
response = fml::MakeRefCounted<PlatformMessageResponseAndroid>(
response_id, jni_facade_, task_runners_.GetPlatformTaskRunner());
}
PlatformView::DispatchPlatformMessage(
std::make_unique<flutter::PlatformMessage>(
std::move(name), std::move(message), std::move(response)));
}
runtime/runtime_controller.cc
// |PlatformConfigurationClient|
void RuntimeController::HandlePlatformMessage(
std::unique_ptr<PlatformMessage> message) {
client_.HandlePlatformMessage(std::move(message));
}
shell/common/shell.cc
// |PlatformView::Delegate|
void Shell::OnPlatformViewDispatchPlatformMessage(
std::unique_ptr<PlatformMessage> message) {
FML_DCHECK(is_setup_);
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
task_runners_.GetUITaskRunner()->PostTask(fml::MakeCopyable(
[engine = engine_->GetWeakPtr(), message = std::move(message)]() mutable {
if (engine) {
engine->DispatchPlatformMessage(std::move(message));
}
}));
}
if (engine) {
engine->DispatchPlatformMessage(std::move(message));
}
shell/common/engine.cc
void Engine::DispatchPlatformMessage(std::unique_ptr<PlatformMessage> message) {
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;
}
if (runtime_controller_->IsRootIsolateRunning() &&
runtime_controller_->DispatchPlatformMessage(std::move(message))) {
return;
}
FML_DLOG(WARNING) << "Dropping platform message on channel: " << channel;
}
runtime/runtime_controller.cc
bool RuntimeController::DispatchPlatformMessage(
std::unique_ptr<PlatformMessage> message) {
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
TRACE_EVENT1("flutter", "RuntimeController::DispatchPlatformMessage",
"mode", "basic");
platform_configuration->DispatchPlatformMessage(std::move(message));
return true;
}
return false;
}
lib/ui/window/platform_configuration.cc
void PlatformConfiguration::DispatchPlatformMessage(
std::unique_ptr<PlatformMessage> message) {
std::shared_ptr<tonic::DartState> dart_state =
dispatch_platform_message_.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);
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;
if (auto response = message->response()) {
response_id = next_response_id_++;
pending_responses_[response_id] = response;
}
tonic::LogIfError(
tonic::DartInvoke(dispatch_platform_message_.Get(),
{tonic::ToDart(message->channel()), data_handle,
tonic::ToDart(response_id)}));
}
binding.dart
@override
Future<void> handlePlatformMessage(
String channel,
ByteData? data,
ui.PlatformMessageResponseCallback? callback,
) async {
ByteData? response;
try {
final MessageHandler? handler = _handlers[channel];
if (handler != null) {
response = await handler(data);
platform_channel.dart
void setMessageHandler(Future<T> Function(T message)? handler) {
if (handler == null) {
binaryMessenger.setMessageHandler(name, null);
} else {
binaryMessenger.setMessageHandler(name, (ByteData? message) async {
return codec.encodeMessage(await handler(codec.decodeMessage(message)));//进入之前设置的回调闭包
});
}
}
lib/messages.dart
static void setup(FlutterRouterApi api) {
{
const BasicMessageChannel<Object> channel =
BasicMessageChannel<Object>('dev.flutter.pigeon.FlutterRouterApi.popRoute', StandardMessageCodec());
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object message) async {
//进入之前设置的Handler回调闭包
assert(message != null, 'Argument for dev.flutter.pigeon.FlutterRouterApi.popRoute was null. Expected CommonParams.');
final CommonParams input = CommonParams.decode(message);
api.popRoute(input);
return;
});
}
MethodChannel支持双向通信,反向原理类似,参考demo: multiple flutters
深入理解Flutter的Platform Channel机制
MethodChannel的执行流程涉及到主线程和UI线程的交互,代码从Dart到C++再到Java层,执行完相应逻辑后原路返回,从Java层到C++层再到Dart层。
[小节3.5] Shell::OnEngineHandlePlatformMessage 将任务发送给主线程
[-> flutter/shell/common/shell.cc]
constexpr char kSkiaChannel[] = "flutter/skia";
void Shell::OnEngineHandlePlatformMessage(
fml::RefPtr<PlatformMessage> message) {
if (message->channel() == kSkiaChannel) {
HandleEngineSkiaMessage(std::move(message));
return;
}
//[见小节3.6]
task_runners_.GetPlatformTaskRunner()->PostTask(
[view = platform_view_->GetWeakPtr(), message = std::move(message)]() {
if (view) {
view->HandlePlatformMessage(std::move(message));
}
});
}
//将HandlePlatformMessage的工作交给主线程的PlatformTaskRunner来处理,对于PlatformView在Android平台的实例为PlatformViewAndroid。
[小节6.5] PlatformMessageResponseDart::Complete 将任务发送给UI线程
[-> flutter/lib/ui/window/platform_message_response_dart.cc]
void PlatformMessageResponseDart::Complete(std::unique_ptr<fml::Mapping> data) {
is_complete_ = true;
//post到UI线程来执行
ui_task_runner_->PostTask(fml::MakeCopyable(
[callback = std::move(callback_), data = std::move(data)]() mutable {
std::shared_ptr<tonic::DartState> dart_state = callback.dart_state().lock();
tonic::DartState::Scope scope(dart_state);
Dart_Handle byte_buffer = WrapByteData(std::move(data));
//[见小节6.6]
tonic::DartInvoke(callback.Release(), {byte_buffer});
}));
}
//到此就发生了线程切换操作,将任务post到UI线程的UITaskRunner来执行。