Flutter与Native通信(二): EventChannel

07/23/2022 10:01 上午 posted in  Flutter

flutter可以native之间可以通过Platform Channels APIs进行通信,API主要有以下三种:

  • [MethodChanel]:用于传递方法调用(method invocation)
  • [EventChannel]:用于事件流的发送(event streams)
  • [MessageChannel]:用于传递字符串和半结构化的消息

其中EventChannel用于从native向flutter发送通知事件,例如flutter通过其监听Android的重力感应变化等。与MethodChannel不同,EventChannel是native到flutter的单向调用,调用是多播(一对多)的,可以类比成Android的Brodcast。

1. EventChannel的基本流程

我们照例先看一下API使用的基本流程:

  1. [native]EventChannel#setStreamHandler注册Handler实现
  2. [native]EventChannel初始化结束后,在StreamHandler#onLister回调中获取EventSink引用并保存
  3. [flutter]EventChannel#receiveBroadcastStream注册listener,建立监听
  4. [native]使用EventSink#sucess发送通知事件
  5. [flutter]接受到事件通知
  6. [native]通知结束时调用endOfStream结束

2.代码实现

flutter端

  • 创建EventChannel,注册“包名/标识符”的channel名
  • 通过StreamSubscription#listen注册listener,其中cancelOnError参数表示遇到错误时是否自动结束监听
class _MyHomePageState extends State<MyHomePage> {
  static const EventChannel _channel = const EventChannel('com.example.eventchannel/interop');
 
  StreamSubscription _streamSubscription;
  String _platformMessage;
 
  void _enableEventReceiver() {
    _streamSubscription = _channel.receiveBroadcastStream().listen(
        (dynamic event) {
          print('Received event: $event');
          setState(() {
            _platformMessage = event;
          });
        },
        onError: (dynamic error) {
          print('Received error: ${error.message}');
        },
        cancelOnError: true);
  }
 
  void _disableEventReceiver() {
    if (_streamSubscription != null) {
      _streamSubscription.cancel();
      _streamSubscription = null;
    }
  }
 
  @override
  initState() {
    super.initState();
    _enableEventReceiver();
  }
 
  @override
  void dispose() {
    super.dispose();
    _disableEventReceiver();
  }

调用StreamSubscriptoin#cancel时,监听被取消。

native(android)端

android需要完成以下功能

  • 通过EventChannel#setStreamHandler注册Handler实现
  • 初始化完成后,获取eventSink引用并保存
  • eventSink发送事件通知
  • 通知结束时调用event#endOfStream,此时onCancel会被调用
  • 必要时,可通过evnetSink#error发送错误通知,flutter的StreamSubscription#onError会收到通知
class MainActivity: FlutterActivity() {
    private lateinit var channel: EventChannel
    var eventSink: EventSink? = null
 
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine)
 
        channel = EventChannel(flutterEngine.dartExecutor.binaryMessenger, "com.example.eventchannel/interop")
        channel.setStreamHandler(
                object : StreamHandler {
                    override fun onListen(arguments: Any?, events: EventSink) {
                        eventSink = events
                        Log.d("Android", "EventChannel onListen called")
                        Handler().postDelayed({
                            eventSink?.success("Android")
                            //eventSink?.endOfStream()
                            //eventSink?.error("error code", "error message","error details")
                        }, 500)
                    }
                    override fun onCancel(arguments: Any?) {
                        Log.w("Android", "EventChannel onCancel called")
                    }
                })
    }
}