Flutter与原生通信之iOS
Flutter 与原生交互有三种方式:
- MethodChannel
- EventChannel
- BasicMessageChannel
==MethodChannel==
是Flutter与原生交互的一种方式,此种方式传递的是方法,可以双向传递,可以携带参数,双向传递都可以有返回值
Flutter给原生端发送消息
- Flutter端代码
csharp
final methodChannel = const MethodChannel('test_method_channel');
Future<void> sendMessageFromMethodChannel() async {
final result = await methodChannel.invokeMethod("method_one");
print(result);
}
定义发送消息 MethodChannel生成对应的channel,需要指定channel的name 发送消息使用的是:invokeMethod 指定方法名,也可以带参数,有返回值
- 原生端代码配置
swift
var channel: FlutterMethodChannel
init(messager: FlutterBinaryMessenger) {
channel = FlutterMethodChannel(name: "test_method_channel", binaryMessenger: messager)
channel.setMethodCallHandler { (call , result) in
print("接收到了来自Flutter发送的方法\(call.method)")
result("我是原生返回给Flutter的消息")
}
}
定义好channel,注册方法 setMethodCallHandler 在AppDelegate入口函数处需要初始化
javascript
let controller = window.rootViewController as! FlutterBinaryMessenger
MethodChannelManager(messager: controller.binaryMessenger)
原生(iOS为例)给Flutter发送消息
- iOS原生端配置
swift
var channel: FlutterMethodChannel
init(messager: FlutterBinaryMessenger) {
channel = FlutterMethodChannel(name: "test_method_channel", binaryMessenger: messager)
channel.setMethodCallHandler { (call , result) in
print("接收到了来自Flutter发送的方法\(call.method)")
result("我是原生返回给Flutter的消息")
self.startTimer()
}
}
func startTimer() {
Timer.scheduledTimer(timeInterval: TimeInterval(2), target: self, selector: #selector(sendMessageToFlutter), userInfo: nil, repeats: false)
}
@objc func sendMessageToFlutter() {
channel.invokeMethod("ios_method", arguments: "我是原生主动发送过来的") {(result) in
print(result)
}
}
原生端发送消息也是调用 invokeMethod,也可以以闭包形式接收到Flutter端的返回值
- Flutter端配置
dart
Future<void> setMethodChannelCallHandler() async {
methodChannel.setMethodCallHandler((call) async {
print('Flutter收到了原生端的方法:${call.method}, 传参为:${call.arguments} ---- call: $call');
return Future.value('我是Flutter回传给原生端的数据');
});
}
@override
void initState() {
// TODO: implement initState
super.initState();
setMethodChannelCallHandler();
}
Flutter中配置的setMethodChannelCallHandler也可以给原生回传数据,直接返回一个 Future即可
==BasicMessageChannel==
也是双向交互,发送字符串和半结构化信息,有返回值
- Flutter端 需要在Flutter端创建一个channel
ini
final basicMessageChannel = const BasicMessageChannel('test_basic_message_channel', StandardMessageCodec());
第一个参数是channel的name 第二个参数是codec
swift
/// The message codec used by this channel, not null.
final MessageCodec<T> codec;
看源码注释,它是一个抽象类,是message的编码和解码机制,这里只需要使用系统默认的标准方式 StandardMessageCodec即可 class StandardMessageCodec implements MessageCodec<Object?>
StandardMessageCodec实现了抽象类 MessageCodec,具体可以看源码 发送消息
csharp
Future<void> sendMessageFromBasicMessageChannel() async {
final result = await basicMessageChannel.send('我是Flutter主动传递给原生的消息');
print(result);
send方法返回值是一个Future,类型是泛型,所以可以通过await获取原生端返回给Flutter的值,下面在原生端会体现。 接收消息
csharp
Future<void> setBasicMessageChannelCallHandler() async {
basicMessageChannel.setMessageHandler((message) async {
print('Flutter收到了原生端的消息:$message');
return Future.value('我是Flutter回传给原生的消息');
});
}
- iOS原生端 定义一个BasicMessageChannelManager管理类,在入口函数中初始化:
javascript
let controller = window.rootViewController as! FlutterBinaryMessenger
BasicMessageChannelManager(messager: controller.binaryMessenger)
接收消息
swift
class BasicMessageChannelManager {
var channel: FlutterBasicMessageChannel
init(messager: FlutterBinaryMessenger) {
channel = FlutterBasicMessageChannel(name: "test_basic_message_channel", binaryMessenger: messager)
channel.setMessageHandler { (message, reply) in
print("原生端收到了来自Flutter端的消息\(message!)")
reply("原生端返回给Flutter端的消息")
}
}
}
在初始化方法中初始化 channel,并配置channel方法监听,message表示Flutter端发送过来的消息,reply是原生端给Flutter返回值的一个闭包 发送消息
scss
@objc func sendMessageToFlutter() {
channel.sendMessage("原生端主动发送给Flutter的消息") {(result) in
print(result!)
}
}
channel通过sendMessage发送消息,可以带上后面的闭包,result为Flutter端返回给原生端的消息
==EventChannel==
是原生向Flutter传递数据流的通道,属于单向传输,只能由原生端调用,Flutter端是接收信息,常见的有网络变化监听,屏幕横竖屏切换,位置切换,电池电量,远程通知等事件。
- Flutter端代码
final eventChannel = const EventChannel('test_event_channel');
定义channel
scss
Future<void> setEventChannel() async {
_streamSubscription = eventChannel.receiveBroadcastStream().listen((event) {
print('Flutter收到了原生端的事件:$event');
}, onError: (error) {
print(error);
}, onDone: () {
print('done');
}, cancelOnError: true);
}
组件初始化中设置回调
- 闭包第一个回调为onData,参数event为泛型,表示原生端返回的信息内容
- onError: 报错会执行
- onDone: 时间完成会执行
- cancelOnError: 报错后是否取消事件
iOS原生端
swift
class EventChannelManager: NSObject {
var channel: FlutterEventChannel
var eventSink: FlutterEventSink?
var count = 0
var timer: Timer?
init(messager: FlutterBinaryMessenger) {
channel = FlutterEventChannel(name: "test_event_channel", binaryMessenger: messager)
}
func config() {
channel.setStreamHandler(**self**)
}
func startTimer() {
timer = Timer(timeInterval: TimeInterval(2), target: self, selector: #selector triggerEventChannel), userInfo: nil, repeats: true)
RunLoop.current.add(timer!, forMode: .common)
}
@objc func triggerEventChannel() {
count += 1
eventSink?("当前数值为:\(count)")
}
}
extension EventChannelManager : FlutterStreamHandler {
func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
self.eventSink = events
startTimer()
return nil
}
func onCancel(withArguments arguments: **Any**?) -> FlutterError? {
return nil
}
}
AppDelegate中调用:
scss
let eventChannelManager = EventChannelManager(messager: messager)
eventChannelManager.config()
和其他两种通信方式不同的是,EventChannel需要在原生端实现 FlutterStreamHandler协议,获取到 FlutterEventSink,用它来进行消息的发送 eventSink?("当前数值为:(count)")