Pigeon

https://github.com/flutter/packages/tree/master/packages/pigeon

Pigeon介绍

Pigeon是Flutter官方推荐的,用于自动生成PlatformChannel通信层模板代码(channel定义,编解码,异常处理等)的package,可以减少通信层开发时间。生成的代码通过MessageChannel进行通信。pigeon则使用MessageChannel并针对每个api方法设置唯一的channelName来进行区分,BasicMessageChannel中的T,也就是request参数和response类型都是Object,并在传输过程中对model进行编解码成Map传输。

Pigeon功能

graph LR
subgraph Pigeon/message.dart
HostApi("@HostApi")
FlutterApi("@FlutterApi")
Class("Define Class")
configurePigeon
end

subgraph server
GenerateFlutterApi
GenereateHostApi
end

subgraph client
GenerateCallHostApi
GenerateCallFullterApi
end

FlutterApi-->|handle in Flutter|GenerateFlutterApi("abstract class FlutterApi:channel.setMessageHandler and delegate to FlutterApi")
GenerateCallHostApi("class HostApi: wrap channel.send")-->|Flutter to host|HostApi

GenerateCallFullterApi("classFlutterApi: wrap channel.send")-->|host to Flutter|FlutterApi
HostApi-->|handle in host|GenereateHostApi("interface HostApi: channel.setMessageHandler and delegate to HostApi")

Pigeon

生成代码

Client端

class NativeNetworkApi {
  Future<Resource> request(RequestParams arg) async {
    final Object encoded = arg.encode();
    const BasicMessageChannel<Object> channel =
        BasicMessageChannel<Object>('dev.flutter.pigeon.NativeNetworkApi.request', StandardMessageCodec());
    final Map<Object, Object> replyMap = await channel.send(encoded) as Map<Object, Object>;
    if (replyMap == null) {
      throw PlatformException(
        code: 'channel-error',
        message: 'Unable to establish connection on channel.',
        details: null,
      );
    } else if (replyMap['error'] != null) {
      final Map<Object, Object> error = (replyMap['error'] as Map<Object, Object>);
      throw PlatformException(
        code: (error['code'] as String),
        message: error['message'] as String,
        details: error['details'],
      );
    } else {
      return Resource.decode(replyMap['result']);
    }
  }

调用方式

NativeNetworkApi().request(requestParams)

Server端

/** Generated interface from Pigeon that represents a handler of messages from Flutter.*/
public interface NativeNetworkApi {
  void request(RequestParams arg, Result<Resource> result);

  /** Sets up an instance of `NativeNetworkApi` to handle messages through the `binaryMessenger`. */
  static void setup(BinaryMessenger binaryMessenger, NativeNetworkApi api) {
    {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.NativeNetworkApi.request", new StandardMessageCodec());
      if (api != null) {
        channel.setMessageHandler((message, reply) -> {
          Map<String, Object> wrapped = new HashMap<>();
          try {
            @SuppressWarnings("ConstantConditions")
            RequestParams input = RequestParams.fromMap((Map<String, Object>)message);
            api.request(input, result -> { wrapped.put("result", result.toMap()); reply.reply(wrapped); });
          }
          catch (Error | RuntimeException exception) {
            wrapped.put("error", wrapError(exception));
            reply.reply(wrapped);
          }
        });
      } else {
        channel.setMessageHandler(null);
      }
    }
    {

配置处理方式

class NetworkPlugin : FlutterPlugin, Messages.NativeNetworkApi {
    /// The MethodChannel that will the communication between Flutter and native Android
    ///
    /// This local reference serves to register the plugin with the Flutter Engine and unregister it
    /// when the Flutter Engine is detached from the Activity
    override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        Messages.NativeNetworkApi.setup(flutterPluginBinding.binaryMessenger, this)
    }

    override fun onDetachedFromEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        Messages.NativeNetworkApi.setup(flutterPluginBinding.binaryMessenger, null)
    }
  
  override fun request(requestParams: Messages.RequestParams, result: Messages.Result<Messages.Resource>) {
    result.success(resource)
  }

@async关键字

Client端

Future<Resource> request(RequestParams arg) async {

Server端

sync时生成的server端handler直接代理到接口实现进行方法调用,无法异步,必须阻塞platform thread

RequestParams input = RequestParams.fromMap((Map<String, Object>)message);
Resource output = api.request(input);
wrapped.put("result", output.toMap());
reply.reply(wrapped);

async时server端handler方法签名多一个参数Result,利用回调实现异步

public interface Result<T> {
   void success(T result);
}
RequestParams input = RequestParams.fromMap((Map<String, Object>)message);
api.request(input, result -> { wrapped.put("result", result.toMap()); reply.reply(wrapped); });

Pigeon原理

https://github.com/flutter/packages/blob/master/packages/pigeon/doc