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

Flutter通过Event Channel从Kotlin获取Spotify SDK数据流遇mEventSink为空问题

解决Flutter Event Channel无法接收Spotify SDK数据流的问题

你遇到的核心问题是MethodChannel和EventChannel使用了完全独立的插件实例,导致你在initEventStream方法里操作的mEventSink,和onListen中初始化的mEventSink根本不是同一个对象——这就是为什么日志会打印mEventSink == null。

问题根源拆解

看你registerWith方法里的代码:

channel.setMethodCallHandler(Spotifysdk04Plugin(registrar))
// ...
eventChannel.setStreamHandler(Spotifysdk04Plugin(registrar))

这里每次调用Spotifysdk04Plugin(registrar)都会生成一个全新的插件对象,处理方法调用的实例和处理事件流的实例完全分离。当Flutter端发起监听触发onListen时,是第二个实例的mEventSink被赋值,但你在initEventStream里访问的是第一个实例的mEventSink,自然一直是null。

修复方案:共用同一个插件实例

只创建一次插件对象,同时给MethodChannel和EventChannel使用:

companion object {
    @JvmStatic fun registerWith(registrar: Registrar) {
        // 创建唯一的插件实例
        val pluginInstance = Spotifysdk04Plugin(registrar)
        
        val channel = MethodChannel(registrar.messenger(), "spotifysdk")
        channel.setMethodCallHandler(pluginInstance)
        
        val eventChannel = EventChannel(registrar.messenger(), "timerStream")
        eventChannel.setStreamHandler(pluginInstance)
    }
}

额外优化建议

  • 确保Flutter端先启动监听再调用initEventStream:只有当Flutter端通过receiveBroadcastStream()发起监听,原生端的onListen才会被调用,mEventSink才会被赋值。Flutter端代码示例:
    final EventChannel _timerChannel = EventChannel('timerStream');
    StreamSubscription? _timerSubscription;
    
    @override
    void initState() {
      super.initState();
      // 先启动监听
      _timerSubscription = _timerChannel.receiveBroadcastStream().listen((position) {
        print('收到播放进度:$position');
      });
      // 再调用初始化数据流的方法
      _channel.invokeMethod('initEventStream');
    }
    
    @override
    void dispose() {
      _timerSubscription?.cancel();
      super.dispose();
    }
    
  • 可以考虑把订阅PlayerState的逻辑移到onListen中:这样能确保只有当mEventSink存在时才开始发送事件,避免空指针风险,比如:
    override fun onListen(arguments: Any?, eventSink: EventChannel.EventSink) {
        mEventSink = eventSink
        // 在这里启动PlayerState订阅
        spotifyAppRemote?.playerApi?.subscribeToPlayerState()
            ?.setEventCallback { playerState ->
                val position = playerState.playbackPosition.toDouble()
                mEventSink?.success(position)
            }
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:52:10