JetPack Compose返回主页时如何销毁共享的SellViewModel?
解决思路与方案
你的核心问题是ViewModel的生命周期没有和sell导航图绑定,导致退出导航图后VM仍驻留内存。以下是具体解决步骤:
问题根源
直接通过new SellViewModel()创建的实例,不会被Jetpack ViewModel的生命周期管理机制接管,其生命周期完全由父Composable(如NavGraph或sellGraph的作用域)决定,而非导航图的回退栈状态。
正确实现方式
利用Navigation Compose的导航图生命周期绑定能力,让ViewModel的生命周期与sell导航图绑定——当整个sell导航图从回退栈中弹出时,ViewModel会自动被销毁。
1. 修改sellGraph,使用ViewModel的正确获取方式
不要手动实例化ViewModel,而是在navigation块内部通过viewModel()方法获取,该方法会自动将VM的生命周期绑定到当前导航图:
fun NavGraphBuilder.sellGraph(navController: NavController) { navigation(startDestination = "mold_brands", route = "sell") { // 绑定到sell导航图的ViewModel,导航图弹出时自动销毁 val vm = viewModel<SellViewModel>() composable("mold_brands") { Brands(nav = navController, vm = vm) } composable("mold_specs") { Specs(nav = navController, vm = vm) } composable("mold_images") { Images(nav = navController, vm = vm) } } }
2. 确保退出时完全弹出sell导航图
从sell导航图内的页面返回主页时,需要明确弹出整个sell导航图,触发ViewModel的销毁:
// 在Brands/Specs/Images等页面的返回逻辑中使用 navController.navigate("home") { // inclusive = true 表示同时弹出sell导航图本身 popUpTo("sell") { inclusive = true } }
3. (可选)进入sell导航图时重置状态
如果需要每次进入sell导航图都创建全新的ViewModel实例,可在导航时配置如下:
// 从Home页面进入sell导航图的逻辑 navController.navigate("sell") { popUpTo("home") { saveState = false } launchSingleTop = true }
补充:使用Hilt的情况
如果项目使用Hilt依赖注入,只需将SellViewModel添加@HiltViewModel注解,然后将viewModel<SellViewModel>()替换为hiltViewModel()即可,生命周期绑定逻辑保持一致:
@HiltViewModel class SellViewModel @Inject constructor() : ViewModel() { // ... 原有逻辑 } // sellGraph中的获取方式 val vm = hiltViewModel<SellViewModel>()
内容的提问来源于stack exchange,提问作者Mohammed Riyadh
相关产品推荐
相关产品推荐

