前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter 即学即用系列博客——09 EventChannel 实现原生与 Flutter 通信(一)

Flutter 即学即用系列博客——09 EventChannel 实现原生与 Flutter 通信(一)

作者头像
AndroidTraveler
发布2019-04-25 15:18:07
8900
发布2019-04-25 15:18:07
举报
文章被收录于专栏:AndroidTraveler
前言

紧接着上一篇,这一篇我们讲一下原生怎么给 Flutter 发信号,即原生-> Flutter

还是通过 Flutter 官网的 Example 来讲解。

案例

接着上一次,这一次我们让原生主动将电池的充电状态发送给 Flutter 并在界面显示。

步骤如下。

1. Flutter 界面修改

我们在原先基础上增加一列用于显示文本。

代码语言:javascript
复制
String _chargingStatus = 'Battery status: unknown.';Text(_chargingStatus),
2. Flutter 定义 EventChannel

我们在 _BatteryWidgetState 里面加入下面变量:

代码语言:javascript
复制
static const EventChannel eventChannel = EventChannel('samples.flutter.io/charging');

samples.flutter.io/charging 可以自己指定,一般保证唯一,所以 samples 实际使用可以替换为包名。主要是要跟原生对应即可。

3. Flutter 在 initState 实现 EventChannel 监听并实现对应回调方法
代码语言:javascript
复制
  @override  void initState() {    super.initState();    eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError);  }
  void _onEvent(Object event) {    setState(() {      _chargingStatus =      "Battery status: ${event == 'charging' ? '' : 'dis'}charging.";    });  }
  void _onError(Object error) {    setState(() {        PlatformException exception = error;        _chargingStatus = exception?.message ?? 'Battery status: unknown.';    });  }

可以看到如果原生发送 charging 显示 charging,否则显示 discharging。

当然错误显示的是原生发送过来的错误信息。

注意这里如果要获取到错误信息,需要通过

代码语言:javascript
复制
PlatformException exception = error;

这个转换语句才可以。

4. 原生定义 EventChannel
代码语言:javascript
复制
private static final String CHARGING_CHANNEL = "samples.flutter.io/charging";

注意需要跟 Flutter 的一一对应。

5. 原生创建 EventChannel 并通过 StreamHandler 的 EventSink 发送内容给 Flutter
代码语言:javascript
复制
new EventChannel((FlutterView) flutterView, CHARGING_CHANNEL).setStreamHandler(        new EventChannel.StreamHandler() {
            @Override            public void onListen(Object arguments, EventChannel.EventSink events) {            }
            @Override            public void onCancel(Object arguments) {            }        });

具体到这里为:

代码语言:javascript
复制
new EventChannel((FlutterView)flutterView, CHARGING_CHANNEL).setStreamHandler(        new EventChannel.StreamHandler() {            private BroadcastReceiver chargingStateChangeReceiver;            @Override            public void onListen(Object arguments, EventChannel.EventSink events) {                chargingStateChangeReceiver = createChargingStateChangeReceiver(events);                registerReceiver(                        chargingStateChangeReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));            }
            @Override            public void onCancel(Object arguments) {                unregisterReceiver(chargingStateChangeReceiver);                chargingStateChangeReceiver = null;            }        });
private BroadcastReceiver createChargingStateChangeReceiver(final EventChannel.EventSink events) {    return new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
            if (status == BatteryManager.BATTERY_STATUS_UNKNOWN) {                events.error("UNAVAILABLE", "Charging status unavailable", null);            } else {                boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||                        status == BatteryManager.BATTERY_STATUS_FULL;                events.success(isCharging ? "charging" : "discharging");            }        }    };}

这里的 events.successevents.error 分别会调用 Flutter 的对应方法。

其中 error 的参数对应 Flutter 的 PlatformException 的参数。

代码语言:javascript
复制
PlatformException({  @required this.code,  this.message,  this.details,}) : assert(code != null);

这里通过广播的方式将电量状态变化发送给 Flutter。

效果如下:

扩展

其实我们点击 Flutter 的 EventChannel,会看到源码里面的 receiveBroadcastStream 方法是对 MethodChannel 做了封装。

代码语言:javascript
复制
Stream<dynamic> receiveBroadcastStream([dynamic arguments]) {    final MethodChannel methodChannel = MethodChannel(name, codec);    StreamController<dynamic> controller;    controller = StreamController<dynamic>.broadcast(onListen: () async {      BinaryMessages.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('listen', arguments);      } catch (exception, stack) {        FlutterError.reportError(FlutterErrorDetails(          exception: exception,          stack: stack,          library: 'services library',          context: 'while activating platform stream on channel $name',        ));      }    }, onCancel: () async {      BinaryMessages.setMessageHandler(name, null);      try {        await methodChannel.invokeMethod('cancel', arguments);      } catch (exception, stack) {        FlutterError.reportError(FlutterErrorDetails(          exception: exception,          stack: stack,          library: 'services library',          context: 'while de-activating platform stream on channel $name',        ));      }    });    return controller.stream;  }

所以其实原生-> Flutter 的通信也是可以用 MethodChannel 直接实现。

那怎么实现呢?

欲知详情,且听下回讲解

本文源码位置: https://github.com/nesger/FlutterSample/tree/feature/event_channel

参考链接:

https://flutter.dev/docs/development/platform-integration/platform-channels https://github.com/flutter/flutter/tree/master/examples/platform_channel

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 安卓小煜 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 案例
    • 1. Flutter 界面修改
      • 2. Flutter 定义 EventChannel
        • 3. Flutter 在 initState 实现 EventChannel 监听并实现对应回调方法
          • 4. 原生定义 EventChannel
            • 5. 原生创建 EventChannel 并通过 StreamHandler 的 EventSink 发送内容给 Flutter
            • 扩展
              • 参考链接:
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档