iT邦幫忙

2021 iThome 鐵人賽

DAY 11
0
Mobile Development

Flutter - 從 Packages & Plugins 掌握原生系列 第 11

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 來實作看看吧


上一篇
Day10 Platform Channel - MethodChannel
下一篇
Day12 開發插件 - 範例程式碼介紹01 Flutter 端
系列文
Flutter - 從 Packages & Plugins 掌握原生30

尚未有邦友留言

立即登入留言