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

Android端MediaPlayer切换歌曲时崩溃问题求助

问题原因

你遇到的IllegalStateException核心问题是MediaPlayer引用管理错误:

  • 第一次切歌时,你释放了全局的MediaPlayer实例,但紧接着创建的是局部变量mediaPlayer,全局引用仍指向已释放的无效实例。
  • 第二次点击时,调用stop()/reset()/release()时,全局实例已经处于被释放的不可用状态,直接触发非法状态异常。
  • 注释掉这些方法后多歌同时播放,是因为每次点击都创建了新的MediaPlayer实例,旧实例未被释放,一直在后台运行。
修复代码

修改切歌逻辑,复用全局MediaPlayer引用,正确管理其生命周期:

// 全局变量改为可空var,方便后续重新赋值
private var mediaPlayer: MediaPlayer? = null

// 启动初始化(注意:MediaPlayer.create已完成prepare,无需手动调用)
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // ...其他初始化代码
    mediaPlayer = MediaPlayer.create(this, R.raw.cant_let_go)
    mediaPlayer?.start()
}

// 切歌点击事件处理
adapter = RVDiffAdapter(object : RVDiffAdapter.OnAdapterListener {
    override fun onCLick(name: String, rawId:Int) {
        Toast.makeText(applicationContext, name, Toast.LENGTH_SHORT).show()

        Log.d("XXX", "name $name")
        Log.d("XXX", "rawId $rawId")

        // 安全处理旧实例:停止播放并释放资源
        mediaPlayer?.let { mp ->
            if (mp.isPlaying) mp.stop()
            mp.release()
        }
        // 重新初始化全局实例并播放
        mediaPlayer = MediaPlayer.create(applicationContext, rawId)
        mediaPlayer?.start()
    }
})
额外注意事项
  1. 避免重复prepare:MediaPlayer.create()内部已经完成了prepare()操作,手动调用会触发另一个IllegalStateException。
  2. Activity生命周期收尾:在onDestroy()中释放资源,防止内存泄漏:
override fun onDestroy() {
    super.onDestroy()
    mediaPlayer?.let {
        if (it.isPlaying) it.stop()
        it.release()
        mediaPlayer = null
    }
}
  1. 空安全检查:始终用?.或let处理MediaPlayer的可空引用,避免空指针异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 20:05:31