Jetpack Compose中应用退至后台时如何停止MediaPlayer?
解决应用退至后台时停止MediaPlayer的问题
问题根源
你当前的DisposableEffect(Unit)只会在Composable被销毁时触发onDispose(比如屏幕旋转引发的重组),但应用退至后台时Composable并未销毁,所以MediaPlayer不会停止。而你写的ViewModel生命周期观察者没生效,核心原因是没有把观察者绑定到Activity/Fragment的Lifecycle实例上。
方法一:用LifecycleEffect监听应用前后台状态
在Compose中可以通过LifecycleEffect直接监听生命周期事件,当应用进入后台状态时暂停/停止播放:
val current = LocalContext.current val player1: MediaPlayer = remember { MediaPlayer.create(current, R.raw.music1) } val lifecycle = LocalLifecycleOwner.current.lifecycle LifecycleEffect(lifecycle) { val observer = LifecycleEventObserver { _, event -> when (event) { Lifecycle.Event.ON_RESUME -> { if (!player1.isPlaying) { player1.start() } } Lifecycle.Event.ON_PAUSE -> { if (player1.isPlaying) { player1.pause() } } Lifecycle.Event.ON_DESTROY -> { player1.release() } } } lifecycle.addObserver(observer) onDispose { lifecycle.removeObserver(observer) player1.release() } } // 初始化播放逻辑 DisposableEffect(Unit) { player1.isLooping = true player1.start() onDispose { player1.stop() player1.release() } }
方法二:修复ViewModel的生命周期绑定
如果想用ViewModel统一管理播放器,需要在宿主组件(Activity/Fragment)中完成生命周期绑定:
- 完善ViewModel逻辑:
class ExampleClass(application: Application) : AndroidViewModel(application) { private var player: MediaPlayer? = null fun initPlayer() { if (player == null) { player = MediaPlayer.create(getApplication(), R.raw.music1) player?.isLooping = true } } fun startPlaying() { player?.start() } fun pausePlaying() { player?.pause() } fun releasePlayer() { player?.stop() player?.release() player = null } }
- 在Activity中绑定生命周期观察者:
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val viewModel = ViewModelProvider(this)[ExampleClass::class.java] lifecycle.addObserver(object : DefaultLifecycleObserver { override fun onResume(owner: LifecycleOwner) { viewModel.initPlayer() viewModel.startPlaying() } override fun onPause(owner: LifecycleOwner) { viewModel.pausePlaying() } override fun onDestroy(owner: LifecycleOwner) { viewModel.releasePlayer() } }) setContent { // 你的Compose页面内容 } } }
关键注意点
- 务必在组件销毁时调用
MediaPlayer.release(),避免内存泄漏和资源占用。 - 应用退至后台时,系统可能会回收资源,建议在
ON_PAUSE事件中暂停播放,ON_DESTROY事件中彻底释放播放器。
内容的提问来源于stack exchange,提问作者Mr.P.Panther
相关产品推荐
相关产品推荐

