D797cdf6f3934affd930b30285a71d9c
底层原理 - 深入探索Platform Channel

Flutter 提供了完善的 Platform Channel 机制供 Native 与 Flutter 端进行相互通信,本节由浅入深,详细探索 Platform Channel 的实现细节。

怎么用

首先我们简单介绍下 Platform Channel 的使用姿势,Flutter提供了三种Channel的方式:

  • BaseMessageChannel,消息的传递,用于数据的传递。
  • MethodChannel,方法的传递,用于方法调用,传递参数并返回执行结果。
  • EventChannel,事件的传递,用于Native端对Flutter端高频的通知触发。

MethodChannel - Android

构造函数,通常messenger传递FlutterNativeView实现的DartExecutor, name是Channel匹配的key值,codec是消息传递的编解码,默认是StandardMethodCodec。

 MethodChannel(BinaryMessenger messenger, String name, MethodCodec codec)

调用Flutter端方法,参数依次是方法名、参数以及返回值的回调。

 invokeMethod(String method, Object arguments, MethodChannel.Result callback)

设置方法被调用的处理器,Flutter调用原生代码会调用handler的onMethodCall方法。

setMethodCallHandler(MethodChannel.MethodCallHandler handler)

MethodChannel - iOS

构造函数

- (instancetype)initWithName:(NSString*)name
             binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger
                       codec:(NSObject<FlutterMessageCodec>*)codec;

调用Flutter方法

- (void)invokeMethod:(NSString*)method
           arguments:(id _Nullable)arguments
              result:(FlutterResult _Nullable)callback

设置方法回调

- (void)setMethodCallHandler:(FlutterMethodCallHandler _Nullable)handler;

MethodChannel - Flutter

构造函数

- MethodChannel(this.name, [this.codec = const StandardMethodCodec()])

调用Native方法

- invokeMethod(String method, [dynamic arguments])

设置方法回调

- setMethodCallHandler(Future<dynamic> handler(MethodCall call))

BaseMessageChannel、EventChannel和MethodChannel的使用方式十分类似,这里就不一一赘述了。

怎么实现的

Platform Channel 以 engine 为媒介,在 native 端或者 dart 端进行消息的编码,经过 engine 传递,在另一端进行消息的解码,完成整个消息的通信。这个过程涉及到 messager (信使)、
codec(编解码器)以及 handler(处理器),下面将分别介绍。

messager

messager 在整个消息传递过程中,作为信使的角色,实现了完整的消息传递。我们看一下 Android 端 BinaryMessenger 的代码,iOS 和 Dart 部分 API 高度一致。

public interface BinaryMessenger {

    void send(String channel, ByteBuffer message);

    void send(String channel, ByteBuffer message, BinaryReply callback);

    void setMessageHandler(String channel, BinaryMessageHandler handler);

    interface BinaryMessageHandler {

        void onMessage(ByteBuffer message, BinaryReply reply);
    }

    interface BinaryReply {

        void reply(ByteBuffer reply);
    }
}

BinaryMessenger 提供了两个 send 方法,可选择是否回调消息的处理结果,提供了 setMessageHandler 用以处理 Dart 端 Channel 调用的消息处理。BinaryMessenger 的一个具体实现在 DartMessenger,维护了 messageHandlers 和 pendingReplies 两个 HashMap 分别处理 Dart 端消息请求的响应以及自己发送消息之后的回调。具体的消息传递的完成流程我们等会再讲,先分析一下 codec(编解码器)和 handler(处理器)的实现细节。

codec

让消息在 dart、engine 以及平台( Android / iOS )之间自由传递,需要将消息在传递前编码为平台无关的二进制数据,在接收后解码为原始的数据格式。Flutter 提供了两种 codec , BaseMessageChannel 使用了 MessageCodec , EventChannel 和 MethodChannel 使用了 MethodCodec。

MessageCodec 提供了 encodeMessage 和 decodeMessage 两个接口,以 Android 为例,它的代码实现如下:

public interface MessageCodec<T> {

    ByteBuffer encodeMessage(T message);

    T decodeMessage(ByteBuffer message);
}

Flutter 官方默认已经实现的 MessageCodec 有 StandardMessageCodec、BinaryCodec、StringCodec、JSONMessageCodec 。默认已经实现的 MethodCodec 有 StandardMethodCodec、JSONMethodCodec。

Codec Desc
MessageCodec StandardMessageCodec 支持基础数据格式与二进制之间的转换,包括 Boolean 、Number、String、Byte、List、Map、数组等。
BinaryCodec 支持二进制数据的直接传递,实际上是没有做任何编解码,可以通过它做大内存块的数据传递。
StringCodec 支持字符串(UTF-8)与二进制之间的转换。
JSONMessageCodec 支持把数据转换为JSON,再调用 StringCodec 的编解码。
MethodCodec StandardMethodCodec 调用 StandardMessageCodec 传递方法的名字和参数。
JSONMethodCodec 调用 JSONMessageCodec 传递方法的名字和参数。

消息的编解码方式可以根据自己的需要从系统提供的 Codec 中选取,也可以完全自定义自己的 Codec 满足实际的业务需求。这里想实现一种基于 Protocol Buffers 协议的编解码器,作为一种简单的学习锻炼,后续会发布在 Github 上供大家参考。

Handler

Flutter 提供了 Handler 作为消息的处理器,用来处理接收方获取的消息。针对 BaseMessageChannel、MethodChannel 和 EventChannel 三种 Channel 分别提供了 IncomingMessageHandler、IncomingMethodCallHandler 和 IncomingStreamRequestHandler 三种 Handler,实际上是分别包装了 MessageHandler 、MethodCallHandler 和 StreamHandler 来处理对方发送过来的消息。

MessageHandler

```
public interface MessageHandler {

top Created with Sketch.