前言

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

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

案例

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

步骤如下。

1. Flutter 界面修改

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

String _chargingStatus = 'Battery status: unknown.';
Text(_chargingStatus),
2. Flutter 定义 EventChannel

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

static const EventChannel eventChannel = EventChannel('samples.flutter.io/charging');

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

3. Flutter 在 initState 实现 EventChannel 监听并实现对应回调方法
  @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。

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

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

PlatformException exception = error;

这个转换语句才可以。

4. 原生定义 EventChannel
private static final String CHARGING_CHANNEL = "samples.flutter.io/charging";

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

5. 原生创建 EventChannel 并通过 StreamHandler 的 EventSink 发送内容给 Flutter
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) {
}
}
);

具体到这里为:

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 的参数。

PlatformException({
@required this.code,
this.message,
this.details,
}) : assert(code != null);

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

效果如下:

扩展

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

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

更多阅读:

Flutter 即学即用系列博客

Flutter 即学即用系列博客——01 环境搭建

Flutter 即学即用系列博客——02 一个纯 Flutter Demo 说明

Flutter 即学即用系列博客——03 在旧有项目引入 Flutter

Flutter 即学即用系列博客——04 Flutter UI 初窥

Flutter 即学即用系列博客——05 StatelessWidget vs StatefulWidget

Flutter 即学即用系列博客——06 超实用 Widget 集锦

Flutter 即学即用系列博客——07 RenderFlex overflowed 引发的思考

Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信

Flutter & dart

dart 如何优雅的避空

Flutter map 妙用及 .. 使用

Flutter 即学即用系列博客——09 EventChannel 实现原生与 Flutter 通信(一)的更多相关文章

  1. Flutter 即学即用系列博客——09 MethodChannel 实现原生与 Flutter 通信(二)

    前言 上一篇我们讲解了如何通过 EventChannel 实现 Android -> Flutter 的通信. 并且也看到了 Flutter 内部 EventChannel 源码也是对 Meth ...

  2. Flutter 即学即用系列博客——03 在旧有项目引入 Flutter

    前言 其实如果打算在实际项目中引入 Flutter,完全将旧有项目改造成纯 Flutter 项目的可能性比较小,更多的是在旧有项目引入 Flutter. 因此本篇我们就说一说如何在旧有项目引入 Flu ...

  3. Flutter 即学即用系列博客总结篇

    前言 迟到的总结篇,其实大家看我之前发的系列博客最后一篇,发文时间是 3 月 29 日.距离现在快两个月了. 主要是因为有很多事情在忙,所以这篇就耽搁了. 今天终于可以跟大家会面了. 系列博客背景 F ...

  4. Flutter 即学即用系列博客——05 StatelessWidget vs StatefulWidget

    前言 上一篇我们对 Flutter UI 有了一个基本的了解. 这一篇我们通过自定义 Widget 来了解下如何写一个 Widget? 然而 Widget 有两个,StatelessWidget 和 ...

  5. Flutter 即学即用系列博客——04 Flutter UI 初窥

    前面三篇可以算是一个小小的里程碑. 主要是介绍了 Flutter 环境的搭建.如何创建 Flutter 项目以及如何在旧有 Android 项目引入 Flutter. 这一篇我们来学习下 Flutte ...

  6. Flutter 即学即用系列博客——08 MethodChannel 实现 Flutter 与原生通信

    背景 前面我们讲了很多 Flutter 相关的知识点,但是我们并没有介绍怎样实现 Flutter 与原生的通信. 比如我在 Flutter UI 上面点击了一个按钮,我希望原生做一些处理,那么原生怎么 ...

  7. Flutter 即学即用系列博客——06 超实用 Widget 集锦

    本篇文章我们来讲讲一些比较常用的 Widget. 大家验证的时候使用下面的代码替换 main.dart 代码,然后在 //TODO 语句返回下面常用 Widget 示例的代码. import 'pac ...

  8. Flutter 即学即用系列博客——02 一个纯 Flutter Demo 说明

    前言 上一篇文章我们搭建好了 Flutter 的开发环境. Flutter 即学即用--01 环境搭建 这一篇我们通过 Flutter 的一个 Demo 来了解下 Flutter. 开发系统:MAC ...

  9. Flutter 即学即用系列博客——10 混淆

    前言 之前的博客我们都是在 debug 的模式下进行开发的. 实际发布到市场或者给到用户的都是 release 包. 而对于 Android 来说,release 包一个重要的步骤就是混淆. Andr ...

随机推荐

  1. springboot redis多数据源

    springboot中默认的redis配置是只能对单个redis库进行操作的. 那么我们需要多个库操作的时候这个时候就可以采用redis多数据源. 本代码参考RedisAutoConfiguratio ...

  2. 转载 python实例手册

    python实例手册 #encoding:utf8# 设定编码-支持中文 0说明 手册制作: 雪松 更新日期: 2013-12-19 欢迎系统运维加入Q群: 198173206 # 加群请回答问题 请 ...

  3. pyqt5实现注册界面并获得文本框内容

    获取框里面的内容,有一个BUG,搞了好久才搞定. __author__ = 'ayew'import sysfrom PyQt5.QtCore import*from PyQt5.QtWidgets ...

  4. B哥竟然也被裁了,聊一聊我的看法

    B哥的故事 B哥是在17年底朋友聚会上认识的一个哥们,因为都是程序员,也聊得来.就加了微信.今年是他北漂的第三个年头了. B哥是从小南方长大的一个男孩,高中学习还凑凑活活,勉强过了二本,上了大学没人管 ...

  5. VulDeePecker:基于深度学习的脆弱性检测系统

    最近的两款软件,VUDDY和VulPecker,假阴性率高而假阳性率低,用于检测由代码克隆引发的漏洞.而如果用于非代码克隆引起的漏洞则会出现高误报率. 本文使用深度学习处理程序中的代码片段,不应由专家 ...

  6. Android版数据结构与算法(七):赫夫曼树

    版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 近期忙着新版本的开发,此外正在回顾C语言,大部分时间没放在数据结构与算法的整理上,所以更新有点慢了,不过既然写了就肯定尽力将这部分完全整理好分享出 ...

  7. 结合JDK源码看设计模式——桥接模式

    前言: 在我们还没学习框架之前,肯定都学过JDBC.百度百科对JDBC是这样介绍的[JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Jav ...

  8. 设计模式系列1:单例模式(Singleton Pattern)

    定义 保证一个类仅有一个实例,并提供一个该实例的全局访问点.  --<设计模式GoF> UML类图 使用场景 当类只能有一个实例并且用户可以从一个众所周知的访问点访问它时. 创建一个对象需 ...

  9. 轻松搞定表白女朋友:Android版APP (零基础也可直接下载软件)

    在我们平时生活当中,经常会看到一些表白女朋友的html网页,但是Android端的表白软件可以说是基本没有,笔者在全网搜了一下,就没有一个可以用的.安卓端可以给人一种定制和精美的感觉,这是网页所做不到 ...

  10. C++11新特性之tie、tuple的应用

    //tuplestd::tuple<int, int, int, int, QString> Thorface::getUserInfoToJudgeOpendoor(QString st ...