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

Flutter Swift StreamHandler处理多监听器时如何移除对应FlutterEventSink

解决方案

核心问题:FlutterStreamHandler的onCancel回调仅会携带和对应onListen一致的arguments参数,不会回传要移除的FlutterEventSink实例,且Swift原生无法直接比较闭包相等,所以需要将arguments与对应的sink绑定存储,才能在onCancel时精准匹配移除。

实现逻辑

  • 修改存储结构,将单纯的sink数组改为存储(参数标识: AnyHashable, 事件回调: FlutterEventSink)的集合
  • onListen时把传入的arguments转为可哈希类型,和sink配对后存入集合
  • onCancel时用传入的arguments作为标识,匹配移除对应的sink项
  • 增加串行队列保证集合操作的线程安全,避免多线程操作出现崩溃

修改后的完整代码

class ConnectionStateStreamHandler: NSObject, DeviceConnectionDelegate, FlutterStreamHandler {
    var plugin: WearablePlugin? = nil
    // 元组数组支持同一参数对应多个监听,也可改用[AnyHashable: FlutterEventSink]字典做单监听限制
    private var eventSinks: [(key: AnyHashable, sink: FlutterEventSink)] = []
    // 串行队列做线程安全保护
    private let operationQueue = DispatchQueue(label: "com.wearableplugin.connectionStreamQueue")
    
    func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        operationQueue.sync {
            guard let key = arguments as? AnyHashable else {
                return FlutterError(code: "INVALID_ARGUMENTS", message: "监听参数必须为可哈希类型", details: nil)
            }
            eventSinks.append((key: key, sink: events))
            return nil
        }
    }

    func onCancel(withArguments arguments: Any?) -> FlutterError? {
        operationQueue.sync {
            guard let key = arguments as? AnyHashable else {
                return FlutterError(code: "INVALID_ARGUMENTS", message: "监听参数必须为可哈希类型", details: nil)
            }
            // 精准移除对应标识的所有sink
            eventSinks.removeAll { $0.key == key }
            return nil
        }
    }
    
    func onConnectionStateChanged(device: Device, connectionState: ConnectionState) {
        operationQueue.sync {
            guard let data = try? jsonEncoder.encode(device), let jsonStr = String(data: data, encoding: .utf8) else {
                return
            }
            eventSinks.forEach { $0.sink(jsonStr) }
        }
    }
}

补充说明

  • 如果不需要支持同一个参数对应多个监听,直接用[AnyHashable: FlutterEventSink]字典存储即可,onListen直接赋值、onCancel直接调用removeValue(forKey:),性能更高。
  • 如果业务不需要传递自定义参数,可以要求Flutter端每次调用listen时生成一个唯一UUID作为参数传入,即可实现无业务参数下的精准匹配移除。
  • 原代码中的强制解析try!建议替换为try?加空判断,避免编码失败导致应用崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 22:27:00