前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 EventChannel 通信 )

【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | Android 端实现 EventChannel 通信 )

作者头像
韩曙亮
发布2023-03-29 15:58:34
1.6K0
发布2023-03-29 15:58:34
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

前言

本博客与 【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | 在 Flutter 端实现 EventChannel 通信 ) 博客相对应 , 该博客中开发 Flutter 的 Dart 端 ;

本博客中开发 Android 中的 Java 端 , 最终目标是二者可以进行信息交流 ;

一、Android 端 EventChannel 构造函数


Android 端 Java 中 , EventChannel 构造函数方法原型如下 :

代码语言:javascript
复制
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

个参数 :

  • BinaryMessenger messenger : 用于 发送 / 接收消息 ;
  • String name : Channel 消息通道的名称 , 该名称必须与 Dart 中的消息通道名称相同 ;
  • MethodCodec codec : 方法编解码器 ;

如果使用 EventChannel(BinaryMessenger messenger, String name) 构造函数 , 不传入 MethodCodec , 那么会传入 标准的方法编解码器 StandardMethodCodec ;

二、Android 端 setStreamHandler 方法


创建了 EventChannel 实例对象后 , 如果要接收 Dart 端发送来的消息 , 需要设置 消息处理器 ;

调用 setStreamHandler 方法 , 可以为 EventChannel 设置一个 消息处理器 ;

EventChannel.setStreamHandler 函数原型如下 :

代码语言:javascript
复制
  /**
   * 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 接口原型如下 :

代码语言:javascript
复制
  /**
   * 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

个方法 :

  • success : 表示接收数据成功 ;
  • error : 表示接收数据出现错误 ;
  • endOfStream : 表示接收数据结束 ;
代码语言:javascript
复制
  /**
   * 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 实例对象 ;

代码语言:javascript
复制
// 初始化 EventChannel 实例对象
EventChannel mEventChannel = new EventChannel(
        mFlutterFragment.getFlutterEngine().getDartExecutor(),
        "EventChannel");

然后 , 为 EventChannel 实例对象设置 EventChannel.StreamHandler ;

代码语言:javascript
复制
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 端发送数据 ;

代码语言:javascript
复制
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 ;

代码语言:javascript
复制
// 初始化 EventChannel 实例对象
mEventChannel = new EventChannel(
        mFlutterFragment.getFlutterEngine().getDartExecutor(),
        "EventChannel");

② Android 端为 EventChannel 设置 EventChannel.StreamHandler ;

代码语言:javascript
复制
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 端注册监听 ;

代码语言:javascript
复制
// 注册 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 发送数据 ;

代码语言:javascript
复制
/**
 * 事件流建立成功会回调该方法
 * @param arguments
 * @param events
 */
@Override
public void onListen(Object arguments, EventChannel.EventSink events) {
    mEventSink = events;
    Log.i(TAG, "事件流建立成功");
}

⑥ Android 端调用 EventChannel.EventSink 发送数据 ;

代码语言:javascript
复制
// 点击按钮 , 向 Flutter 端发送数据
if (mEventSink != null) {
    mEventSink.success("Native 通过 EventChannel 通道发送消息 Hello !");
}

⑦ Flutter 端接收到 Android 端发送的数据 ; 回调 listen 方法的如下匿名方法参数 ;

代码语言:javascript
复制
(message) {
  print("Flutter _eventChannel listen 回调");
  setState(() {
    /// 接收到消息 , 显示在界面中
    showMessage = message;
  });

上述流程 , 必须按照顺序执行 , 否则注册监听失败 ;

五、相关资源


参考资料 :

重要的专题 :

博客源码下载 :

  • GitHub 地址 : ( 随博客进度一直更新 , 有可能没有本博客的源码 )
代码语言:txt
复制
- **Flutter Module 工程 :** [https://github.com/han1202012/flutter\_module](https://github.com/han1202012/flutter_module)
- **Android 应用 :** [https://github.com/han1202012/flutter\_native](https://github.com/han1202012/flutter_native)
- **注意 : 上面两个工程要放在同一个目录中 , 否则编译不通过 ;**
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-08-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 前言
  • 一、Android 端 EventChannel 构造函数
  • 二、Android 端 setStreamHandler 方法
  • 三、Android 端实现 EventChannel 通信步骤
  • 四、 Android 端与 Flutter 端 EventChannel 注册与监听流程
  • 五、相关资源
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档