Flutter定义了三种不同类型的Channel,它们分别是
- BasicMessageChannel:用于传递字符串和半结构化的信息,这个用的比较少
- MethodChannel:用于传递方法调用(method invocation)通常用来调用native中某个方法
- EventChannel: 用于数据流(event streams)的通信。有监听功能,比如电量变化之后直接推送数据给flutter端。
目前我的项目中只使用了MethodChannel,所以下面主要以MethodChannel部分代码演示。
如果你还想了解其他2种Channel,可以查看下面这篇文章
https://www.jianshu.com/p/39575a90e820
1. Native层
let flutterChannel = FlutterMethodChannel(name: "srs.flutter.io/flutter", binaryMessenger: flutterViewController)
// 注册方法等待flutter页面调用
flutterChannel.setMethodCallHandler { (call, result) in
NSLog("Srs==> call.method:\(call.method)")
NSLog("Srs==> arguments:\(String(describing: call.arguments))")
// 返回的err给flutter
if call.method == "getNativeErrResult" {
let error: FlutterError = FlutterError(code: "UNAVAILABLE", message: "info unavailable", details: "UNAVAILABLE=>info unavailable")
result(error)
} else if call.method == "getNativeScsResult" {
// 通过result返回给Flutter回调结果
let name = ["name": "Srs"]
result(name)
} else if call.method == "dismiss" {
// 跳出页面
VCManager.popTopView()
} else if call.method == "next" {
// 原生调用了Flutter方法
flutterChannel.invokeMethod("getFlutterResult", arguments: ["name": "Srs"], result: { (result) in
NSLog("Srs==> Flutter Result:\(result)")
})
} else {
result(FlutterMethodNotImplemented)
}
}
这里使用的iOS代码,Android端代码也类似。首先通过设置MethodCall的监听,然后根据method处理Flutter端需要的操作逻辑。如果是"next"的时候,原生调用Flutter方法。
2. Flutter层
const platform = const MethodChannel('srs.flutter.io/flutter'); // 交互通道
// 等待Native调用
platform.setMethodCallHandler((methodCall) {
debugPrint("Srs===> flutter===> methodCall.method " + methodCall.method);
// 获取参数
var arguments = new Map<String, dynamic>.from(methodCall.arguments);
debugPrint(
"Srs===> flutter===> methodCall.arguments " + arguments.toString());
return Future.value({"key1": "value1", "key2": "value2"});
});
// 调用Native
Future<void> invokeNative() async {
String backString;
try {
var result = await platform.invokeMethod('dismiss', {});
backString = 'Native return $result';
} on PlatformException catch (e) {
backString = "Failed to get native return: '${e.message}'.";
}
debugPrint("Srs===> flutter==>flutter:" + backString);
}
invokeNative();
首先通过设置MethodCall的监听,同样可以根据method处理Native端需要的操作逻辑, 我这里直接返回数据了。另外通过invokeMethod来调用Native方法。
通信传递过程
Flutter具体是怎么和Native传递消息的呢,本文在https://www.jianshu.com/p/39575a90e820和https://juejin.im/post/5c88be3cf265da2d9809403d基础上进行了整理。
- Flutter端使用invokeMethod方法发起方法调用
- invokeMethod方法会将其入参message和arguments封装成一个MethodCall对象,并使用MethodCodec将其编码为二进制格式数据
- 通过BinaryMessages将消息发出
BinaryMessenger是Native端与Flutter端通信的工具,其通信使用的消息格式为二进制格式数据。
binaryMessager.png
大概格式类似于这样:
BinaryMessenger = [BinaryMessageHandler,BinaryMessageHandler...]
BinaryMessageHandler = {"channel name": Handler}
也就是一个项目可以多个channel,上面示例代码只有一个channel。
- 最终调用到ui.window.sendPlatformMessage方法,至此进入C++层
在C++层通过类似Java的JNI技术给Native层发消息,最终会被Native端预先注册的Window_sendPlatformMessage接受到。
- sendPlatformMessage首先会把来自Flutter端的三个参数(name、data、callback)创建成一个PlatformMessage对象,就是C++认识的对象,
- 接着进入PlatformView的HandlePlatformMessage
2.1 针对iOS直接进入PlatformMessageRouter根据Channel找到对应的Handle处理,处理完根据PlatformMessage里面Response返回给Flutter。
2.2 针对Android,因为JAVA无法直接和C++通信,要多一步JNI操作。PlatformView会通过JNI发送到Java层FlutterNativeView的handlePlatformMessage方法,在该方法里面根据Channel找到对应的Handle处理,处理完再通过JNI返回给PlatformView,根据PlatformMessage里面Response返回给Flutter。
至此,一次从Flutter发起的方法调用就完整结束了。
网友评论