https://github.com/flutter/packages/tree/master/packages/pigeon
Pigeon是Flutter官方推荐的,用于自动生成PlatformChannel通信层模板代码(channel定义,编解码,异常处理等)的package,可以减少通信层开发时间。生成的代码通过MessageChannel进行通信。pigeon则使用MessageChannel并针对每个api方法设置唯一的channelName来进行区分,BasicMessageChannel中的T,也就是request参数和response类型都是Object,并在传输过程中对model进行编解码成Map传输。
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")
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)
/** 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)
}
Future<Resource> request(RequestParams arg) async {
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); });
https://github.com/flutter/packages/blob/master/packages/pigeon/doc