如何在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
相关产品推荐
相关产品推荐

