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

Jetpack Compose中MediaPlayer的正确暂停方式及后台暂停实现方案

Jetpack Compose 中MediaPlayer暂停及后台自动停止实现方案

1. 正确暂停MediaPlayer的标准写法

暂停操作必须做状态校验,避免调用无效状态的MediaPlayer抛出异常:

  • 调用pause()前先判断实例是否存活、是否处于播放状态
  • 暂停后如果长期不需要播放,要及时调用release()释放资源,置空实例避免野指针调用
    核心代码示例:
fun pauseMediaPlayer() {
    mediaPlayer?.takeIf { it.isPlaying }?.pause()
    // 若需要完全释放资源新增以下代码
    // mediaPlayer?.release()
    // mediaPlayer = null
}

注意不要在Composable函数中直接实例化MediaPlayer,会导致每次重组都创建新的实例,出现异常播放、状态丢失的问题,建议用ViewModel或者rememberSaveable持有实例

2. 应用退后台自动暂停的实现方案

核心逻辑是绑定页面/应用生命周期,监听退后台事件触发暂停操作:

步骤1:在Compose页面注册生命周期观察者

使用DisposableEffect绑定生命周期,避免内存泄漏,监听到ON_STOP事件(页面不可见/应用退后台)时触发暂停:

@Composable
fun SoundListPage(viewModel: SoundViewModel = viewModel()) {
    val lifecycleOwner = LocalLifecycleOwner.current
    // 注册生命周期监听
    DisposableEffect(lifecycleOwner) {
        val lifecycleObserver = LifecycleEventObserver { _, event ->
            // 退后台时自动暂停
            if (event == Lifecycle.Event.ON_STOP) {
                viewModel.pauseCurrentSound()
            }
            // 可选:回到前台自动恢复播放
            // if (event == Lifecycle.Event.ON_START) {
            //     viewModel.resumeCurrentSound()
            // }
        }
        lifecycleOwner.lifecycle.addObserver(lifecycleObserver)
        // 页面销毁时移除观察者
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(lifecycleObserver)
        }
    }
    // 你的音效列表UI实现
    LazyColumn {
        items(soundList) { item ->
            SoundItem(
                soundData = item,
                onItemClick = { viewModel.playSound(item) }
            )
        }
    }
}

步骤2:ViewModel中实现播放、暂停逻辑

用ViewModel持有MediaPlayer实例,页面销毁时自动释放资源:

class SoundViewModel : ViewModel() {
    private var currentMediaPlayer: MediaPlayer? = null
    // 你的音效列表数据
    val soundList = emptyList<SoundItem>()

    // 点击列表项播放对应音效
    fun playSound(soundItem: SoundItem) {
        // 先释放之前的播放实例
        currentMediaPlayer?.run {
            stop()
            release()
        }
        currentMediaPlayer = MediaPlayer().apply {
            setDataSource(soundItem.audioPath)
            prepareAsync()
            setOnPreparedListener { start() }
        }
    }

    // 暂停当前播放的音效
    fun pauseCurrentSound() {
        currentMediaPlayer?.takeIf { it.isPlaying }?.pause()
    }

    // ViewModel销毁时释放所有资源
    override fun onCleared() {
        super.onCleared()
        currentMediaPlayer?.release()
        currentMediaPlayer = null
    }
}

可选优化点

  • 新增音频焦点监听,其他应用播放音频时自动暂停你的音效
  • 监听MediaPlayer播放完成回调,自动释放资源
  • 新增播放状态的状态变量,同步更新UI的播放/暂停状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 04:48:03