Flutter中MethodChannel/EventChannel的原理

前言

Flutter开发中或多或少都需要和原生端做一些交互,Flutter SDK中也为开发者提供了MethodChannel/EventChannel实现了Flutter调用原生端以及原生端调用Flutter。

MethodChannel

Flutter与原生端方法调用使用的是MethodChannel,它是双向通信Flutter和原生端都可以主动发起

Flutter端调用原生方法
  • Flutter端调用
const MethodChannel _channel =
    MethodChannel("com.test.methodChannel/test");
_channel.invokeMethod("getVersion", {// 如果有参数就传参数,键值对形式});
  • Android端实现
        MethodChannel methodChannel = new MethodChannel(flutterView.getAttachedFlutterEngine().getDartExecutor(),
        "com.test.methodChannel/test");

        methodChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
            @Override
            public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
                        switch (call.method){
                            case "getVersion":
                                result.success(1);
                                break;
                        }
            }
        });
原生调用Flutter方法
  • Flutter端实现
  MethodChannel methodChannel = MethodChannel("com.test.methodChannel/test");
  methodChannel.setMethodCallHandler((MethodCall call){
    Completer completer = Completer();
    switch(call.method){
      case "getFlutterInfo":
        completer.complete("Flutter Package Name is Test");
        break;
    }
    return completer.future;

  });
  • Android端调用
               MethodChannel methodChannel = new MethodChannel(flutterView.getAttachedFlutterEngine().getDartExecutor(),
        "com.test.methodChannel/test");
        methodChannel.invokeMethod("getFlutterInfo", null, new MethodChannel.Result() {
            @Override
            public void success(@Nullable Object result) {
                //拿到Flutter中getFlutterInfo方法的结果 Flutter Package Name is Tes
            }

            @Override
            public void error(String errorCode, @Nullable String errorMessage, @Nullable Object errorDetails) {

            }

            @Override
            public void notImplemented() {

            }
        });

EventChannel

EventChannel是原生端与Flutter端相互发送事件,它是单向通信的,实现原理和MethodChannel差不多

原生端发送事件到Flutter
  • Flutter端监听代码
EventChannel _eventChannel = EventChannel('com.test.eventChannel/test');
//监听原生端发送过来的事件
_eventChannel.receiveBroadcastStream().listener()
  • Android端发送代码
        EventChannel eventChannel = new EventChannel(flutterView.getAttachedFlutterEngine().getDartExecutor(),"com.test.eventChannel/test");
       EventChannel.EventSink eventSink;
        
        eventChannel.setStreamHandler(new EventChannel.StreamHandler() {
            @Override
            public void onListen(Object arguments, EventChannel.EventSink events) {
                
               eventSink = events;
            }

            @Override
            public void onCancel(Object arguments) {

            }
        });
        
//发送事件到Flutter
if(eventSink != null){
		eventSink.success(200);
}        

核心类/方法调用示意图(Flutter / Android)

Flutter中MethodChannel/EventChannel的原理_第1张图片

信使DartMessenger/_DefaultBinaryMessenger

无论是MethodChannel还是EventChannel它们都是面向业务上层封装好的API。查看源码可以得知Android有一个DartMessenger,而Flutter端有一个_DefaultBinaryMessenger,这两者负责接收消息和发送消息。

MethodChannel方法调用链:
  • Flutter端
  1. MethodChannel#invokeMethod
  2. _DefaultBinaryMessenger#send

PlatformDispatcher#_sendPlatformMessage

  • Android端
  1. FlutterJNI#handlePlatformMessage
  2. DartMessenger#handleMessageFromDart
  3. IncomingMethodCallHandler#onMessage
  4. MethodCallHandler#onMethodCall
  5. Reply#reply //返回值
  6. FlutterJNI#invokePlatformMessageResponseCallback
EventChannel方法调用链:
  • Android端
  1. EventChannel#setStreamHandler
  2. Flutter端注册监听
  3. EventSink#success
  4. DartMessenger#send
  5. FlutterJNI.dispatchPlatformMessage
  • Flutter端
  1. EventChannel#receiveBroadcastStream#binaryMessenger.setMessageHandler

  2. PlatformDispatcher#_dispatchPlatformMessage

  3. window.onPlatformMessage

  4. _DefaultBinaryMessenger#handlePlatformMessage

  5. 调用2.中的setMessageHandler的回调

编码器

Flutter与原生之间的交互的数据都是要经过二进制编码的,Flutter framework提供了StandardMessageCodec编码器,最终都是基于二进制传输,所以默认只支持String,int,double,bool,List,Map这几类数据的传输

总结:

通过本文分析Flutter跨端通信的流程加深对Flutter跨平台的认识,从语言层面它是Java --> C/C++ —> Dart 的一个调用。从整体架构上来看分为消息处理器、编码器、信使、消息传输等结构,类比JsBridge等框架结构类似。

你可能感兴趣的:(Flutter,flutter,android,ios)