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

