You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中通过EventChannel接收Android端发送的字符串流

实现方案

1. 修复Flutter端插件Stream定义

现有代码的messageStream没有正确返回流对象,导致无法收到原生端发送的事件,修正后代码如下:

static const EventChannel messageChannel = EventChannel('eventChannelStream');

Stream<String> get messageStream {
  // 直接返回转类型后的广播流,可按需增加数据校验逻辑
  return messageChannel.receiveBroadcastStream().cast<String>();
}

如果需要在Flutter层做自定义数据处理,可以调整为:

Stream<String> get messageStream {
  return messageChannel.receiveBroadcastStream().map((event) {
    // 此处添加自定义处理逻辑
    return event as String;
  });
}

注意请确保Flutter和原生两端的MethodChannel、EventChannel名称完全一致,避免无法建立通信

2. 安卓端实现多事件延迟发送

在MethodCallHandler的对应触发方法中,使用Kotlin协程实现间隔发送多条消息,补充代码如下:

class HelperPlugin : FlutterPlugin, MethodCallHandler, EventChannel.StreamHandler {

    private lateinit var channel: MethodChannel
    private var messageChannel: EventChannel? = null
    private var eventSink: EventChannel.EventSink? = null
    // 定义协程作用域管理发送任务
    private val coroutineScope = CoroutineScope(Dispatchers.Main.immediate)

    override fun onListen(arguments: Any?, eventSink: EventChannel.EventSink?) {
        this.eventSink = eventSink
    }

    override fun onCancel(arguments: Any?) {
        // 取消未完成的发送任务,避免内存泄漏
        coroutineScope.cancel()
        eventSink = null
        messageChannel = null
    }

    override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        channel = MethodChannel(flutterPluginBinding.binaryMessenger, "methodChannel")
        channel.setMethodCallHandler(this)

        messageChannel = EventChannel(flutterPluginBinding.binaryMessenger, "eventChannelStream")
        messageChannel?.setStreamHandler(this)
    }

    override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
        when (call.method) {
            // 假设触发消息发送的方法名为startSendMessages
            "startSendMessages" -> {
                // 接收Flutter端传入的字符串列表,也可以在原生端生成列表
                val messageList = call.argument<List<String>>("messageList") ?: emptyList()
                coroutineScope.launch {
                    messageList.forEachIndexed { index, msg ->
                        // 两条消息之间间隔1500ms,可自定义时长
                        if (index != 0) delay(1500)
                        // 发送前校验eventSink有效性避免空指针
                        eventSink?.success(msg)
                    }
                    // 全部发送完成后可按需调用endOfStream关闭流
                    // eventSink?.endOfStream()
                    result.success(null)
                }
            }
            else -> result.notImplemented()
        }
    }
}

如果需要在非主线程发送消息,必须手动切换到主线程调用eventSink?.success()方法,否则会触发通信异常。

3. BLoC侧使用调整

现有retrieveMessage逻辑可直接使用,在BLoC事件处理方法中正确订阅流即可,示例如下:

on<StartReceiveMessageEvent>((event, emit) async {
  // 先调用MethodChannel触发原生端开始发送消息
  await methodChannel.invokeMethod('startSendMessages', {
    'messageList': ['第一条消息', '第二条消息', '第三条消息'] // 可传入自定义字符串列表
  });
  // 订阅流接收原生端发送的消息
  await emit.forEach(
    retrieveMessage(pluginInstance.messageStream),
    onData: (String message) {
      // 把收到的消息封装为状态发送给UI层
      return MessageUpdateState(content: message);
    },
    onError: (error, stackTrace) {
      // 处理通信异常
      return MessageErrorState(error: error.toString());
    }
  );
});

如果需要在Flutter层控制消息发送间隔,把retrieveMessage中注释的Future.delayed代码打开即可,不需要原生端做延迟处理。

内容的提问来源于stack exchange,提问作者kalinor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 08:57:02