本篇源码分析基于以下环境
[?] Flutter (Channel stable, 2.2.3, on macOS 11.4 20F71 darwin-x64, locale
zh-Hans-CN)
? Flutter version 2.2.3 at /Users/liangchaojie/Documents/flutter
? Framework revision f4abaa0735 (6 weeks ago), 2021-07-01 12:46:11 -0700
? Engine revision 241c87ad80
? Dart version 2.13.4
? Pub download mirror https://pub.flutter-io.cn
? Flutter download mirror https://storage.flutter-io.cn
1 demo_plugin.dart
class DemoPlugin {
static const MethodChannel _channel =
const MethodChannel('demo_plugin');
static Future<String> get platformVersion {
return _channel.invokeMethod('getPlatformVersion');
}
}
2 platform_channel.dart
@optionalTypeArgs
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 {
final BinaryMessenger? _binaryMessenger;
final ByteData? result = await binaryMessenger.send(name,codec.encodeMethodCall(MethodCall(method, arguments)),
);
return codec.decodeEnvelope(result) as T?;
}
3 binding.dart
@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.PlatformDispatcher.instance.sendPlatformMessage(channel, message, (ByteData? reply) {
try {
completer.complete(reply);
} catch (exception, stack) {
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'services library',
context: ErrorDescription('during a platform message response callback'),
));
}
});
return completer.future;
}
4 platform_dispatcher.dart
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 'PlatformConfiguration_sendPlatformMessage';
5 platform_configuration.cc
这个文件注册了很多Dart 调用 Native 方法的集合,这里全部列举出来,后续看其他代码的时候或许会用到
void PlatformConfiguration::RegisterNatives(
tonic::DartLibraryNatives* natives) {
natives->Register({
{"PlatformConfiguration_defaultRouteName", DefaultRouteName, 1, true},
{"PlatformConfiguration_scheduleFrame", ScheduleFrame, 1, true},
{"PlatformConfiguration_sendPlatformMessage", _SendPlatformMessage, 4,
true},
{"PlatformConfiguration_respondToPlatformMessage",
_RespondToPlatformMessage, 3, true},
{"PlatformConfiguration_respondToKeyData", _RespondToKeyData, 3, true},
{"PlatformConfiguration_render", Render, 3, true},
{"PlatformConfiguration_updateSemantics", UpdateSemantics, 2, true},
{"PlatformConfiguration_setIsolateDebugName", SetIsolateDebugName, 2,
true},
{"PlatformConfiguration_reportUnhandledException",
ReportUnhandledException, 2, true},
{"PlatformConfiguration_setNeedsReportTimings", SetNeedsReportTimings, 2,
true},
{"PlatformConfiguration_getPersistentIsolateData",
GetPersistentIsolateData, 1, true},
{"PlatformConfiguration_computePlatformResolvedLocale",
_ComputePlatformResolvedLocale, 2, 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) {
UIDartState* dart_state = UIDartState::Current();
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)) {
response = fml::MakeRefCounted<PlatformMessageResponseDart>(
tonic::DartPersistentValue(dart_state, callback),
dart_state->GetTaskRunners().GetUITaskRunner());
}
if (Dart_IsNull(data_handle)) {
dart_state->platform_configuration()->client()->HandlePlatformMessage(
std::make_unique<PlatformMessage>(name, response));
} else {
tonic::DartByteData data(data_handle);
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
dart_state->platform_configuration()->client()->HandlePlatformMessage(
std::make_unique<PlatformMessage>(
name, fml::MallocMapping::Copy(buffer, data.length_in_bytes()),
response));
}
return Dart_Null();
}
6 ui_dart_state.h
PlatformConfiguration* platform_configuration() const {
return platform_configuration_.get();
}
7 platform_configuration.h
class PlatformConfiguration final {
PlatformConfigurationClient* client() const { return client_; }
}
class PlatformConfigurationClient {
public:
virtual void HandlePlatformMessage(
std::unique_ptr<PlatformMessage> message) = 0;
}
8 runtime_controller.h / runtime_controller.cc
runtime_controller.h
class RuntimeController : public PlatformConfigurationClient {
RuntimeDelegate& client_;
}
runtime_controller.cc
void RuntimeController::HandlePlatformMessage(
std::unique_ptr<PlatformMessage> message) {
client_.HandlePlatformMessage(std::move(message));
}
8 runtime_delegate.h
class RuntimeDelegate {
virtual void HandlePlatformMessage(
std::unique_ptr<PlatformMessage> message) = 0;
};
9 engine.h/engine.cc
engine.h
class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
class Delegate {
virtual void OnEngineHandlePlatformMessage(
std::unique_ptr<PlatformMessage> message) = 0;
}
void HandlePlatformMessage(std::unique_ptr<PlatformMessage> message) override;
}
engine.cc
void Engine::HandlePlatformMessage(std::unique_ptr<PlatformMessage> message) {
if (message->channel() == kAssetChannel) {
HandleAssetPlatformMessage(std::move(message));
} else {
delegate_.OnEngineHandlePlatformMessage(std::move(message));
}
}
10 shell.h / shell.cc
shell.h
class Shell final : public PlatformView::Delegate,
public Animator::Delegate,
public Engine::Delegate,
public Rasterizer::Delegate,
public ServiceProtocol::Handler {
void OnEngineHandlePlatformMessage(
std::unique_ptr<PlatformMessage> message) override;
}
shell.cc
void Shell::OnEngineHandlePlatformMessage(
std::unique_ptr<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(
fml::MakeCopyable([view = platform_view_->GetWeakPtr(),
message = std::move(message)]() mutable {
if (view) {
view->HandlePlatformMessage(std::move(message));
}
}));
}
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);
11 platform_view_android.h / platform_view_android.cc
void PlatformViewAndroid::HandlePlatformMessage(
std::unique_ptr<flutter::PlatformMessage> message) {
int response_id = 0;
if (auto response = message->response()) {
response_id = next_response_id_++;
pending_responses_[response_id] = response;
}
jni_facade_->FlutterViewHandlePlatformMessage(std::move(message),
response_id);
message = nullptr;
}
12 platform_view_android_jni_impl.cc
void PlatformViewAndroidJNIImpl::FlutterViewHandlePlatformMessage(
std::unique_ptr<flutter::PlatformMessage> message,
int responseId) {
JNIEnv* env = fml::jni::AttachCurrentThread();
auto java_object = java_object_.get(env);
if (java_object.is_null()) {
return;
}
fml::jni::ScopedJavaLocalRef<jstring> java_channel =
fml::jni::StringToJavaString(env, message->channel());
if (message->hasData()) {
fml::jni::ScopedJavaLocalRef<jobject> message_array(
env, env->NewDirectByteBuffer(
const_cast<uint8_t*>(message->data().GetMapping()),
message->data().GetSize()));
env->CallVoidMethod(java_object.obj(), g_handle_platform_message_method,
java_channel.obj(), message_array.obj(), responseId);
} else {
env->CallVoidMethod(java_object.obj(), g_handle_platform_message_method,
java_channel.obj(), nullptr, responseId);
}
FML_CHECK(fml::jni::CheckException(env));
}
g_handle_platform_message_method =
env->GetMethodID(g_flutter_jni_class->obj(), "handlePlatformMessage",
"(Ljava/lang/String;Ljava/nio/ByteBuffer;I)V");
13 FlutterJNI.java
@SuppressWarnings("unused")
@VisibleForTesting
public void handlePlatformMessage(
@NonNull final String channel, ByteBuffer message, final int replyId) {
if (platformMessageHandler != null) {
platformMessageHandler.handleMessageFromDart(channel, message, replyId);
}
}
@UiThread
public void setPlatformMessageHandler(@Nullable PlatformMessageHandler platformMessageHandler) {
ensureRunningOnMainThread();
this.platformMessageHandler = platformMessageHandler;
}
14 DartExecutor.java
public void onAttachedToJNI() {
Log.v( TAG, "Attached to JNI. Registering the platform message handler for this Dart execution context.");
flutterJNI.setPlatformMessageHandler(dartMessenger);
}
public DartExecutor(@NonNull FlutterJNI flutterJNI, @NonNull AssetManager assetManager) {
this.dartMessenger = new DartMessenger(flutterJNI);
this.dartMessenger.setMessageHandler("flutter/isolate", this.isolateChannelMessageHandler);
this.binaryMessenger = new DartExecutor.DefaultBinaryMessenger(this.dartMessenger);
}
private static class DefaultBinaryMessenger implements BinaryMessenger {
private final DartMessenger messenger;
private DefaultBinaryMessenger(@NonNull DartMessenger messenger) {
this.messenger = messenger;
}
@UiThread
public void send(@NonNull String channel, @Nullable ByteBuffer message) {
this.messenger.send(channel, message, (BinaryReply)null);
}
@UiThread
public void send(@NonNull String channel, @Nullable ByteBuffer message, @Nullable BinaryReply callback) {
this.messenger.send(channel, message, callback);
}
@UiThread
public void setMessageHandler(@NonNull String channel, @Nullable BinaryMessageHandler handler) {
this.messenger.setMessageHandler(channel, handler);
}
}
15 DartMessenger.java
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);
handler.onMessage(buffer, new DartMessenger.Reply(this.flutterJNI, replyId));
}
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);
}
}
16 DartExecutor.java
@Deprecated
@UiThread
public void setMessageHandler(@NonNull String channel, @Nullable BinaryMessageHandler handler) {
this.binaryMessenger.setMessageHandler(channel, handler);
}
17 MethodChannel.java
@UiThread
public void setMethodCallHandler(@Nullable MethodChannel.MethodCallHandler handler) {
this.messenger.setMessageHandler(this.name, handler == null ? null : new MethodChannel.IncomingMethodCallHandler(handler));
}
18 DemoPlugin.java
public class DemoPlugin implements FlutterPlugin, MethodCallHandler {
private MethodChannel channel;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "demo_plugin");
channel.setMethodCallHandler(this);
}
public static void registerWith(Registrar registrar) {
final MethodChannel channel = new MethodChannel(registrar.messenger(), "demo_plugin");
channel.setMethodCallHandler(new DemoPlugin());
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
if (call.method.equals("getPlatformVersion")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
} else if (call.method.equals("getPlatformVersion2")) {
result.success("Android " + android.os.Build.VERSION.RELEASE);
}else {
result.notImplemented();
}
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
channel.setMethodCallHandler(null);
}
}
|