用户离开屏幕时如何销毁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
相关产品推荐
相关产品推荐

