为什么Jetpack Compose Navigation每个路由都会创建新的ViewModel?
核心原因
viewModel()方法的实例复用范围完全绑定ViewModelStoreOwner,默认情况下Composable中调用该方法时,会使用最近的上层ViewModelStoreOwner作为作用域:
- 如果你使用Navigation Compose实现页面路由,每个导航目的地(NavBackStackEntry)本身就是独立的ViewModelStoreOwner,你在两个页面Composable中分别调用
viewModel(),各自绑定当前页面的NavBackStackEntry,自然会创建两个独立的ViewModel实例,每次进入新页面都会触发init执行。 - 你的理解没有偏差,
viewModel()确实只会在同个ViewModelStoreOwner下找不到对应实例时才会新建,问题出在默认使用的作用域不符合你的共享需求。
解决方案
根据你的共享范围需求选择对应实现:
1. 全局Activity范围共享
适合需要整个应用生命周期内共享的ViewModel,调用时显式指定ViewModelStoreOwner为当前Activity即可:
@Composable fun HelloScreen(helloViewModel: HelloViewModel = viewModel( viewModelStoreOwner = LocalContext.current as ComponentActivity ))
该方式下ViewModel生命周期和宿主Activity完全绑定,Activity销毁时才会被回收。
2. 部分关联页面共享(仅Navigation Compose场景)
如果仅需要在某几个关联的路由页面间共享ViewModel,可以指定作用域为共同的父导航图实例:
@Composable fun HelloScreen( navController: NavController, helloViewModel: HelloViewModel = viewModel( viewModelStoreOwner = navController.getBackStackEntry("父导航图的路由ID") ) )
该方式下ViewModel的生命周期和父导航图绑定,父导航图出栈时才会回收ViewModel,不会占用全局生命周期。
内容的提问来源于stack exchange,提问作者jpm
相关产品推荐
相关产品推荐

