MethodChannel

整体设计

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

EngineUi线程接收消息模块设计

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

类结构设计

MethodChannel

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

MessageChannel

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。

注册监听MethodChannel().setMethodCallHandler((call, result) -> {})

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

Wrap handler with IncomingMethodCallHandler

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.setMessageHandler

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);
   }
 }

IncomingMethodCallHandler.onMessage

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));
     }

发起调用methodChannel.invokeMethod

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;

codec.encodeMethodCall

ByteData result = await binaryMessenger.send

/// 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;

ui.window.SendPlatformMessage

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)),

Shell::OnEngineHandlePlatformMessage

// |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();
}

PlatformViewAndroid::HandlePlatformMessage

// |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);

DartMessenger.handleMessageFromDart

@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);
   }
 }

BinaryMessageHandler.onMessage

消息回复

Reply.reply

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     //
      );
}

PlatformViewAndroid::InvokePlatformMessageResponseCallback

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)));
}

PlatformMessageResponseDart::Complete

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的第三个参数闭包
      }));
}

sendplatformmessage

MethodCodec

 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;
    }

反向(Native调用Dart)原理

Native侧platformThread

DispatchPlatformMessage

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));
}

GetUITaskRunner()->PostTask

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));
        }
      }));
}

Dart侧(UI Thread)

      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和原生之间的平台通道实践与原理

深入理解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来执行。