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

用户离开屏幕时如何销毁ViewModel?Hilt注入的SplashViewModel内存残留如何处理

问题根因

Jetpack Compose Navigation 中,每个composable路由对应的页面都会生成独立的NavBackStackEntry,通过hiltViewModel()获取的ViewModel默认绑定到对应Entry的ViewModelStore中,只有当Entry被从回退栈移除时,ViewModel才会触发onCleared()完成销毁。
你当前的跳转逻辑只是将主页面压入回退栈顶部,启动屏的Entry仍然保留在回退栈中,所以对应的SplashViewModel会一直驻留内存。

解决方案(适配启动屏场景)

启动屏本身不需要保留在回退栈中,跳转主页面时直接将启动屏从回退栈弹出即可,对应的ViewModel会自动销毁:
在SplashScreen中加载完成执行跳转的逻辑修改为如下:

// 示例:加载完成后跳转逻辑
LaunchedEffect(loadState) {
    if (loadState.isSuccess) {
        navController.navigate("main") {
            // 弹出回退栈直到splash路由,inclusive = true表示把splash页面一起弹出
            popUpTo("splash") {
                inclusive = true
            }
            // 可选配置:避免重复触发跳转生成多个主页面实例
            launchSingleTop = true
        }
    }
}
验证销毁生效

你可以在SplashViewModel中重写onCleared方法打印日志,执行跳转后如果日志触发,说明ViewModel已经被正常销毁:

@HiltViewModel
class SplashViewModel @Inject constructor (private val repository: Repository) : ViewModel() {
    // ....其他逻辑
    override fun onCleared() {
        super.onCleared()
        Log.d("SplashViewModel", "onCleared 触发,实例已销毁")
    }
}
异常排查

如果配置上述跳转逻辑后ViewModel仍未销毁,需要排查内存泄漏问题:

  • 检查是否有长生命周期对象(比如单例Repository、全局静态变量、运行中的后台协程/任务)持有了SplashViewModel的引用
  • 检查是否在其他页面错误获取了SplashViewModel的实例,延长了它的生命周期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 01:00:05