FlutterFlutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 EventChannel 通信 )
Posted 韩曙亮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FlutterFlutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 EventChannel 通信 )相关的知识,希望对你有一定的参考价值。
文章目录
前言
本博客与 【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | 在 Flutter 端实现 EventChannel 通信 ) 博客相对应 , 该博客中开发 Flutter 的 Dart 端 ;
本博客中开发 android 中的 Java 端 , 最终目标是二者可以进行信息交流 ;
一、Android 端 EventChannel 构造函数
Android 端 Java 中 , EventChannel 构造函数方法原型如下 :
public final class EventChannel {
private static final String TAG = "EventChannel#";
private final BinaryMessenger messenger;
private final String name;
private final MethodCodec codec;
/**
* Creates a new channel associated with the specified {@link BinaryMessenger} and with the
* specified name and the standard {@link MethodCodec}.
*
* @param messenger a {@link BinaryMessenger}.
* @param name a channel name String.
*/
public EventChannel(BinaryMessenger messenger, String name) {
this(messenger, name, StandardMethodCodec.INSTANCE);
}
/**
* Creates a new channel associated with the specified {@link BinaryMessenger} and with the
* specified name and {@link MethodCodec}.
*
* @param messenger a {@link BinaryMessenger}.
* @param name a channel name String.
* @param codec a {@link MessageCodec}.
*/
public EventChannel(BinaryMessenger messenger, String name, MethodCodec codec) {
if (BuildConfig.DEBUG) {
if (messenger == null) {
Log.e(TAG, "Parameter messenger must not be null.");
}
if (name == null) {
Log.e(TAG, "Parameter name must not be null.");
}
if (codec == null) {
Log.e(TAG, "Parameter codec must not be null.");
}
}
this.messenger = messenger;
this.name = name;
this.codec = codec;
}
}
BasicMessageChannel 接收 3 3 3 个参数 :
- BinaryMessenger messenger : 用于 发送 / 接收消息 ;
- String name : Channel 消息通道的名称 , 该名称必须与 Dart 中的消息通道名称相同 ;
- MethodCodec codec : 方法编解码器 ;
如果使用 EventChannel(BinaryMessenger messenger, String name) 构造函数 , 不传入 MethodCodec , 那么会传入 标准的方法编解码器 StandardMethodCodec ;
二、Android 端 setStreamHandler 方法
创建了 EventChannel 实例对象后 , 如果要接收 Dart 端发送来的消息 , 需要设置 消息处理器 ;
调用 setStreamHandler 方法 , 可以为 EventChannel 设置一个 消息处理器 ;
EventChannel.setStreamHandler 函数原型如下 :
/**
* Registers a stream handler on this channel.
*
* <p>Overrides any existing handler registration for (the name of) this channel.
*
* <p>If no handler has been registered, any incoming stream setup requests will be handled
* silently by providing an empty stream.
*
* @param handler a {@link StreamHandler}, or null to deregister.
*/
@UiThread
public void setStreamHandler(final StreamHandler handler) {
messenger.setMessageHandler(
name, handler == null ? null : new IncomingStreamRequestHandler(handler));
}
设置的 final @Nullable StreamHandler handler 参数 , 就是 消息处理器 ;
在 StreamHandler 接口中 , 定义了两个接口方法 : onListen 和 onCancel 方法 ;
void onListen(Object arguments, EventSink events) : 用于接收 Dart 端所发送的消息 ;
- Object arguments 参数 : Dart 端发送的数据 ;
- EventSink events 参数 : Android 中收到了 Dart 端数据 , 要回调 Dart 时回调的函数 ;
StreamHandler 接口原型如下 :
/**
* Handler of stream setup and teardown requests.
*
* <p>Implementations must be prepared to accept sequences of alternating calls to {@link
* #onListen(Object, EventSink)} and {@link #onCancel(Object)}. Implementations should ideally
* consume no resources when the last such call is not {@code onListen}. In typical situations,
* this means that the implementation should register itself with platform-specific event sources
* {@code onListen} and deregister again {@code onCancel}.
*/
public interface StreamHandler {
/**
* Handles a request to set up an event stream.
*
* <p>Any uncaught exception thrown by this method will be caught by the channel implementation
* and logged. An error result message will be sent back to Flutter.
*
* @param arguments stream configuration arguments, possibly null.
* @param events an {@link EventSink} for emitting events to the Flutter receiver.
*/
void onListen(Object arguments, EventSink events);
/**
* Handles a request to tear down the most recently created event stream.
*
* <p>Any uncaught exception thrown by this method will be caught by the channel implementation
* and logged. An error result message will be sent back to Flutter.
*
* <p>The channel implementation may call this method with null arguments to separate a pair of
* two consecutive set up requests. Such request pairs may occur during Flutter hot restart. Any
* uncaught exception thrown in this situation will be logged without notifying Flutter.
*
* @param arguments stream configuration arguments, possibly null.
*/
void onCancel(Object arguments);
}
EventSink 接口中 , 有 3 3 3 个方法 :
- success : 表示接收数据成功 ;
- error : 表示接收数据出现错误 ;
- endOfStream : 表示接收数据结束 ;
/**
* Event callback. Supports dual use: Producers of events to be sent to Flutter act as clients of
* this interface for sending events. Consumers of events sent from Flutter implement this
* interface for handling received events (the latter facility has not been implemented yet).
*/
public interface EventSink {
/**
* Consumes a successful event.
*
* @param event the event, possibly null.
*/
void success(Object event);
/**
* Consumes an error event.
*
* @param errorCode an error code String.
* @param errorMessage a human-readable error message String, possibly null.
* @param errorDetails error details, possibly null
*/
void error(String errorCode, String errorMessage, Object errorDetails);
/**
* Consumes end of stream. Ensuing calls to {@link #success(Object)} or {@link #error(String,
* String, Object)}, if any, are ignored.
*/
void endOfStream();
}
三、Android 端实现 EventChannel 通信步骤
Android 端实现 EventChannel 通信步骤 :
首先 , 初始化 EventChannel 实例对象 ;
// 初始化 EventChannel 实例对象
EventChannel mEventChannel = new EventChannel(
mFlutterFragment.getFlutterEngine().getDartExecutor(),
"EventChannel");
然后 , 为 EventChannel 实例对象设置 EventChannel.StreamHandler ;
mEventChannel.setStreamHandler(new EventChannel.StreamHandler() {
/**
* 事件流建立成功会回调该方法
* @param arguments
* @param events
*/
@Override
public void onListen(Object arguments, EventChannel.EventSink events) {
mEventSink = events;
Log.i(TAG, "事件流建立成功");
}
@Override
public void onCancel(Object arguments) {
mEventSink = null;
}
});
最后 , 调用 EventChannel.EventSink 的 success 方法 , 向 Flutter 端发送数据 ;
findViewById(R.id.channel2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i(TAG, "Native 通过 EventChannel 通道发送消息 , mEventSink : " + mEventSink);
// 点击按钮 , 向 Flutter 端发送数据
if (mEventSink != null) {
mEventSink.success("Native 通过 EventChannel 通道发送消息 Hello !");
}
}
});
注意 : 这里要特别注意 , Android 与 Flutter 中 EventChannel 的初始化流程 , 先初始化 Android 中的 EventChannel , 再初始化 Flutter 中的 EventChannel , 如果顺序不对 , 无法进行通信 ;
【错误记录】Flutter 混合开发报错 ( Android 端与 Flutter 端 EventChannel 初始化顺序错误导致无法通信 | EventChannel 通信流程 )
四、 Android 端与 Flutter 端 EventChannel 注册与监听流程
Android 端与 Flutter 端 EventChannel 注册与监听流程 :
① Android 端 初始化 EventChannel ;
// 初始化 EventChannel 实例对象
mEventChannel = new EventChannel(
mFlutterFragment.getFlutterEngine().getDartExecutor(),
"EventChannel");
② Android 端为 EventChannel 设置 EventChannel.StreamHandler ;
mEventChannel.setStreamHandler(new EventChannel.StreamHandler() {
/**
* 事件流建立成功会回调该方法
* @param arguments
* @param events
*/
@Override
public void onListen(Object arguments, EventChannel.EventSink events) {
mEventSink = events;
Log.i(TAG, "事件流建立成功");
}
@Override
public void onCancel(Object arguments) {
mEventSink = null;
}
});
③ Flutter 端注册监听 ;
// 注册 EventChannel 监听
_streamSubscription = _eventChannel
.receiveBroadcastStream()
/// StreamSubscription<T> listen(void onData(T event)?,
/// {Function? onError, void onDone()?, bool? cancelOnError});
.listen(
/// EventChannel 接收到 Native 信息后 , 回调的方法
(message) {
print("Flutter _eventChannel listen 回调");
setState(() {
/// 接收到消息 , 显示在界面中
showMessage = message;
});
},
onError: (error){
print("Flutter _eventChannel listen 出错");
print(error);
}
);
④ Android 端的 EventChannel.StreamHandler 接口的 onListen 回调 , 此时可以在 Android 端持有 EventChannel.EventSink events , 可以借助该对象向 Flutter 发送数据 ;
/**
* 事件流建立成功会回调该方法
* @param arguments
* @param events
*/
@Override
public void onListen(Object arguments, EventChannel.EventSink events) {
mEventSink = events;
Log.i(TAG, "事件流建立成功");
}
⑥ Android 端调用 EventChannel.EventSink 发送数据 ;
// 点击按钮 , 向 Flutter 端发送数据
if (mEventSink != null) {
mEventSink.success("Native 通过 EventChannel 通道发送消息 Hello !");
}
⑦ Flutter 端接收到 Android 端发送的数据 ; 回调 listen 方法的如下匿名方法参数 ;
(message) {
print("Flutter _eventChannel listen 回调");
setState(() {
/// 接收到消息 , 显示在界面中
showMessage = message;
});
上述流程 , 必须按照顺序执行 , 否则注册监听失败 ;
五、相关资源
参考资料 :
- Flutter 官网 : https://flutter.dev/
- Flutter 插件下载地址 : https://pub.dev/packages
- Flutter 开发文档 : https://flutter.cn/docs ( 强烈推荐 )
- 官方 GitHub 地址 : https://github.com/flutter
- Flutter 中文社区 : https://flutter.cn/
- Flutter 实用教程 : https://flutter.cn/docs/cookbook
- Flutter CodeLab : https://codelabs.flutter-io.cn/
- Dart 中文文档 : https://dart.cn/
- Dart 开发者官网 : https://api.dart.dev/
- Flutter 中文网 : https://flutterchina.club/ , http://flutter.axuer.com/docs/
- Flutter 相关问题 : https://flutterchina.club/faq/ ( 入门阶段推荐看一遍 )
- GitHub 上的 Flutter 开源示例 : https://download.csdn.net/download/han1202012/15989510
- Flutter 实战电子书 : https://book.flutterchina.club/chapter1/
- Dart 语言练习网站 : https://dartpad.dartlang.org/
重要的专题 :
- Flutter 动画参考文档 : https://flutterchina.club/animations/
博客源码下载 :
-
GitHub 地址 : ( 随博客进度一直更新 , 有可能没有本博客的源码 )
- Flutter Module 工程 : https://github.com/han1202012/flutter_module
- Android 应用 : https://github.com/han1202012/flutter_native
- 注意 : 上面两个工程要放在同一个目录中 , 否则编译不通过 ;
-
博客源码快照 : https://download.csdn.net/download/han1202012/21670919 ( 本篇博客的源码快照 , 可以找到本博客的源码 )
以上是关于FlutterFlutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 EventChannel 通信 )的主要内容,如果未能解决你的问题,请参考以下文章
FlutterFlutter 混合开发 ( Flutter 与 Native 通信 | 完整代码示例 )
FlutterFlutter 混合开发 ( Dart 代码调试 | Flutter 单独调试 | 混合模式下 Flutter 调试 )
FlutterFlutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 MethodChannel 通信 )
FlutterFlutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 BasicMessageChannel 通信 )
FlutterFlutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 EventChannel 通信 )
FlutterFlutter 混合开发 ( 安卓端向 Flutter 传递数据 | FlutterFragment 数据传递 | FlutterActivity 数据传递 )