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

如何修复Kotlin Compose中lateinit变量引发的MediaPlayer生命周期问题

解决Compose中MediaPlayer关闭应用后仍播放的问题

你的问题根源在于把Compose的状态变量暴露给了Activity,而Composable的初始化时机确实可能晚于Activity的onResume,导致空指针或者播放状态异常。另外全局变量的方式也不符合Compose的状态管理规范,容易引发生命周期不一致的问题。

这里提供两种可靠的解决方案:


方案一:用ViewModel管理MediaPlayer + 监听Compose生命周期

ViewModel的生命周期和Activity/Fragment绑定,能安全管理MediaPlayer的创建、播放、暂停和释放,避免生命周期不同步的问题。

1. 创建AudioViewModel

import android.content.Context
import android.media.MediaPlayer
import androidx.lifecycle.ViewModel

class AudioViewModel : ViewModel() {
    private var mediaPlayer: MediaPlayer? = null

    // 初始化MediaPlayer,仅在首次调用时创建
    fun initPlayer(context: Context) {
        if (mediaPlayer == null) {
            mediaPlayer = MediaPlayer.create(context, R.raw.ost)
            mediaPlayer?.isLooping = true // 根据需求设置是否循环
        }
    }

    // 开始播放
    fun start() {
        mediaPlayer?.takeIf { !it.isPlaying }?.start()
    }

    // 暂停播放
    fun pause() {
        mediaPlayer?.takeIf { it.isPlaying }?.pause()
    }

    // 释放资源,避免内存泄漏
    private fun release() {
        mediaPlayer?.stop()
        mediaPlayer?.release()
        mediaPlayer = null
    }

    // ViewModel销毁时自动释放资源
    override fun onCleared() {
        super.onCleared()
        release()
    }
}

2. 在Compose中使用ViewModel并监听生命周期

import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.viewmodel.compose.viewmodel

@Composable
internal fun MainContext() {
    val context = LocalContext.current
    val audioViewModel = viewModel<AudioViewModel>()
    val lifecycleOwner = LocalLifecycleOwner.current

    // 监听生命周期,同步播放状态
    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            when (event) {
                androidx.lifecycle.Lifecycle.Event.ON_RESUME -> audioViewModel.start()
                androidx.lifecycle.Lifecycle.Event.ON_PAUSE -> audioViewModel.pause()
                else -> {}
            }
        }
        lifecycleOwner.lifecycle.addObserver(observer)
        // 组件销毁时移除观察者
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }

    // 初始化MediaPlayer,仅执行一次
    LaunchedEffect(Unit) {
        audioViewModel.initPlayer(context)
    }

    // 你的游戏UI内容
    // ...
}

3. 简化Activity代码

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MainContext()
        }
    }
}

方案二:直接在Compose中使用DisposableEffect管理MediaPlayer

如果不需要ViewModel的配置变化保留能力,也可以直接在Composable内部管理MediaPlayer,结合DisposableEffect处理生命周期:

@Composable
internal fun MainContext() {
    val context = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current
    var mediaPlayer: MediaPlayer? = null

    DisposableEffect(lifecycleOwner) {
        // 初始化MediaPlayer
        mediaPlayer = MediaPlayer.create(context, R.raw.ost)
        mediaPlayer?.isLooping = true

        val observer = LifecycleEventObserver { _, event ->
            when (event) {
                androidx.lifecycle.Lifecycle.Event.ON_RESUME -> mediaPlayer?.start()
                androidx.lifecycle.Lifecycle.Event.ON_PAUSE -> mediaPlayer?.pause()
                else -> {}
            }
        }
        lifecycleOwner.lifecycle.addObserver(observer)

        // 组件销毁时释放资源
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
            mediaPlayer?.stop()
            mediaPlayer?.release()
        }
    }

    // 你的游戏UI内容
    // ...
}

关键说明

  1. 避免全局变量:Compose的状态应该由Composable或ViewModel管理,不要暴露给Activity,否则会导致生命周期不同步。
  2. 必须释放资源:MediaPlayer使用后一定要调用release(),否则会造成音频资源泄漏,甚至影响其他应用的音频播放。
  3. 生命周期监听:使用DisposableEffect绑定Composable的生命周期,比Activity的onResume/onPause更贴合Compose的组件生命周期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 10:23:13