Day11 Platform Channel - EventChannel

EventChannel

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,在StreamControlleronListen 函式中注册了MessageHandler来处理讯息的接收,在接收到讯息之後会将其存到 StreamController 中,StreamController 负责将讯息传送到它的监听者们
之後就是向 Native 呼叫 listen 方法,然後开始接收讯息,在onCancel 函式中透过呼叫Native 的cancel方法来取消讯息接收,让 Native 中的 EventChannel 做一些结尾工作等

而Native 端(以 android 为例),EventChannel通过呼叫setStreamHandler方法,StreamHandler会由上层实作并提供,负责具体的处理逻辑,它有 onListenonCancel 两个方法,onListen 提供了 arguments(引数)和 events(用於传送讯息、报错和结束连线),而 onCancel 只提供了 argments 引数

  public interface StreamHandler {
    void onListen(Object arguments, EventSink events);
    void onCancel(Object arguments);
  }

setStreamHandler中,EventChannelStreamHandler封装到IncomingStreamRequestHandler中,IncomingStreamRequestHandler中的onMessage就是Native 端接收到讯息之後的回拨方法,当接收到呼叫listen方法的讯息时会呼叫onListen函式,在 onListen中会再呼叫 StreamHandleronListen函式,Native 中的 EventChannel也可以通过呼叫EventSink.endOfStream来结束连线,它会向 Flutter 中传送一个null讯息,在 Flutter 中接收到null讯息时便会呼叫 StreamController.close来结束接收讯息

以上就对Flutter 与 Native 的通讯处理做了初步的介绍,接下来让我们来创建一个Flutter Plugin 来实作看看吧


<<:  铁人赛 Day26 -- 一定要知道的JQuery (二) -- 锚点动画

>>:  Day26:Dynamic Programming(DP) - 动态规划(下)

温馨鬼故事 - 网购我的爱,我的个资跟着订单出去了

温馨鬼故事 - 网购我的爱,我的个资跟着订单出去了 Credit: Drake 故事开始 以下故事纯...

DAY 26- 分叉 Fork

「———≡」 分叉 网路上的传播是有时间误差的,也就是说如果今天 A 矿工成功挖到矿,并把挖到的区块...

Day 05:简写好用一直用-v-on、v-bind

延续上篇最後提到 Webpack 设置了别名「@」来取代路径「/src」,然而在模版语法中,「@」则...

Day14 - 在 Next.js 如何做 authentication

Authentication 在 web 应用中经常需要验证使用者的权限,例如登入与未登入能看到的页...

day 1 - 魔鬼藏在细节里

前言 程序写了一阵子之後,工程师就会发展出自己习惯的模式,小到命名方式,大到系统架构,而在我们团队中...