EventChannel:用於接收一系列讯息,这些讯息被包装到 Stream 中,receiveBroadcastStream
返回一个 Stream 物件,可以在 Stream 上新增监听者,然後开始呼叫 Native 端的 listen
方法後,Native 中对应的 EventChannel
就会开始处理讯息,在处理的过程中可以传送多条讯息,这些讯息在传到 Flutter 後都会被加入到 Stream 中,然後通知所有的监听者,其中 EventChannel
有以下几种特色
在 listen
开始之前,Native 端的 EventChannel
无法主动开始运作,当 Flutter 中 Stream 的第一个监听者成功新增时,才会向 Native 呼叫 listen
方法,此时二者之间建立连线并开始运作
在 listen
的过程中间,二者并不能进行交流,Native 层呼叫 listen
方法後就开始不断发送讯息,Flutter 中也只能通过 Stream 不断接收讯息
二者都可以主动结束连线,在 Native 中可以呼叫 EventSink.endOfStream
结束连线,在 Flutter 中移除 Stream 的所有监听者也可以结束连线。如果需要再次建立连线,就需要向 Stream 中新增监听者
在EventChannel
中,二者向对方传送讯息时都不需要接收返回的结果,而是直接通过新的send
途径向对方传送讯息,这是 EventChannel
与其他两种Platflrm Channel 最大的不同,EventChannel
呼叫receiveBroadcastStream
来取得一个 Stream 物件,後续上层主要是通过在 Stream 中新增监听来完成对 Native 端讯息的接收等操作
Stream<dynamic> receiveBroadcastStream([ dynamic arguments ]) {
final MethodChannel methodChannel = MethodChannel(name, codec);
StreamController<dynamic> controller;
controller = StreamController<dynamic>.broadcast(onListen: () async {
defaultBinaryMessenger.setMessageHandler(name, (ByteData reply) async {
if (reply == null) {
controller.close();
} else {
try {
controller.add(codec.decodeEnvelope(reply));
} on PlatformException catch (e) {
controller.addError(e);
}
}
return null;
});
try {
await methodChannel.invokeMethod<void>('listen', arguments);
} catch (exception, stack) {
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'services library',
context: ErrorDescription('while activating platform stream on channel $name'),
));
}
}, onCancel: () async {
defaultBinaryMessenger.setMessageHandler(name, null);
try {
await methodChannel.invokeMethod<void>('cancel', arguments);
} catch (exception, stack) {
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'services library',
context: ErrorDescription('while de-activating platform stream on channel $name'),
));
}
});
return controller.stream;
}
receiveBroadcastStream
在呼叫之後会先生成一个 MethodChannel
来呼叫 Native 端方法,之後建立一个 StreamController
,在StreamController
的 onListen
函式中注册了MessageHandler
来处理讯息的接收,在接收到讯息之後会将其存到 StreamController
中,StreamController
负责将讯息传送到它的监听者们
之後就是向 Native 呼叫 listen
方法,然後开始接收讯息,在onCancel
函式中透过呼叫Native 的cancel
方法来取消讯息接收,让 Native 中的 EventChannel
做一些结尾工作等
而Native 端(以 android 为例),EventChannel
通过呼叫setStreamHandler
方法,StreamHandler
会由上层实作并提供,负责具体的处理逻辑,它有 onListen
和 onCancel
两个方法,onListen
提供了 arguments(引数)和 events(用於传送讯息、报错和结束连线),而 onCancel
只提供了 argments 引数
public interface StreamHandler {
void onListen(Object arguments, EventSink events);
void onCancel(Object arguments);
}
在setStreamHandler
中,EventChannel
将 StreamHandler
封装到IncomingStreamRequestHandler
中,IncomingStreamRequestHandler
中的onMessage
就是Native 端接收到讯息之後的回拨方法,当接收到呼叫listen
方法的讯息时会呼叫onListen
函式,在 onListen
中会再呼叫 StreamHandler
的 onListen
函式,Native 中的 EventChannel
也可以通过呼叫EventSink.endOfStream
来结束连线,它会向 Flutter 中传送一个null
讯息,在 Flutter 中接收到null
讯息时便会呼叫 StreamController.close
来结束接收讯息
以上就对Flutter 与 Native 的通讯处理做了初步的介绍,接下来让我们来创建一个Flutter Plugin 来实作看看吧
<<: 铁人赛 Day26 -- 一定要知道的JQuery (二) -- 锚点动画
>>: Day26:Dynamic Programming(DP) - 动态规划(下)
温馨鬼故事 - 网购我的爱,我的个资跟着订单出去了 Credit: Drake 故事开始 以下故事纯...
「———≡」 分叉 网路上的传播是有时间误差的,也就是说如果今天 A 矿工成功挖到矿,并把挖到的区块...
延续上篇最後提到 Webpack 设置了别名「@」来取代路径「/src」,然而在模版语法中,「@」则...
Authentication 在 web 应用中经常需要验证使用者的权限,例如登入与未登入能看到的页...
前言 程序写了一阵子之後,工程师就会发展出自己习惯的模式,小到命名方式,大到系统架构,而在我们团队中...