Android Compose:如何在Dialog与Composable导航间共享ViewModel?
问题说明
当前代码可实现同一导航图下Composable之间的ViewModel共享,但Dialog与Composable无法复用同一个ViewModel实例,两者的ViewModel哈希值不一致。
原代码
navigation(startDestination = Stage.First.name, route = "main") { dialog(Stage.First.name){ it.provideViewModel<MyViewModel> { vm -> MyDialog(vm) } } composable(Stage.Second.name) { it.provideViewModel<MyViewModel> { vm -> Second(vm) } } composable(Stage.Third.name) { it.provideViewModel<MyViewModel> { vm -> Third(vm) } } } @Composable inline fun <reified T : ViewModel> NavBackStackEntry.provideViewModel( content: @Composable (T) -> Unit ) { val parentId = destination.parent!!.id val parentEntry = remember(this) { navCon.getBackStackEntry(parentId) } val viewModel = hiltViewModel<T>(parentEntry) "vmHashcode".log("${destination.route} : ${viewModel.hashCode()}") content(viewModel) }
问题原因
原代码通过destination.parent!!.id关联ViewModel作用域,但Dialog的导航条目在父节点back stack entry的处理逻辑上与Composable存在差异,导致两者获取的父节点entry并非同一个,最终创建了独立的ViewModel实例。
解决方案
修改provideViewModel函数,直接通过导航图的固定route获取对应的back stack entry,确保Dialog和Composable绑定到同一个导航图层级的ViewModel作用域:
修改后的工具函数
@Composable inline fun <reified T : ViewModel> NavBackStackEntry.provideViewModel( navGraphRoute: String, content: @Composable (T) -> Unit ) { val navController = navController val parentEntry = remember(this) { navController.getBackStackEntry(navGraphRoute) } val viewModel = hiltViewModel<T>(parentEntry) "vmHashcode".log("${destination.route} : ${viewModel.hashCode()}") content(viewModel) }
修改后的导航调用
navigation(startDestination = Stage.First.name, route = "main") { dialog(Stage.First.name){ // 传入当前导航图的route "main" it.provideViewModel<MyViewModel>("main") { vm -> MyDialog(vm) } } composable(Stage.Second.name) { it.provideViewModel<MyViewModel>("main") { vm -> Second(vm) } } composable(Stage.Third.name) { it.provideViewModel<MyViewModel>("main") { vm -> Third(vm) } } }
原理说明
通过导航图的明确route获取对应的back stack entry,强制Dialog和Composable将ViewModel作用域绑定到同一个导航图层级,彻底避免了依赖destination.parent带来的不确定逻辑,确保ViewModel实例的共享一致性。
内容的提问来源于stack exchange,提问作者권오성
相关产品推荐
相关产品推荐

