Hilt ViewModel未随Composable销毁,如何单独绑定其生命周期?
解决方案:让底部弹窗ViewModel绑定自身Composable生命周期
默认情况下,hiltViewModel()会使用当前Composable所属的NavBackStackEntry作为ViewModelStoreOwner,这就导致ViewModel的生命周期和父页面绑定,只有父页面从导航栈移除时才会销毁。要让每个底部弹窗的ViewModel独立绑定自身Composable的生命周期,可以通过以下方式实现:
步骤1:创建绑定Composable生命周期的ViewModelStoreOwner
定义一个Composable扩展函数,生成一个与当前Composable生命周期绑定的ViewModelStoreOwner,并在Composable销毁时自动清理ViewModelStore:
@Composable fun rememberBottomSheetViewModelStoreOwner(): ViewModelStoreOwner { val lifecycle = LocalLifecycleOwner.current.lifecycle val viewModelStore = remember { ViewModelStore() } val savedStateRegistry = rememberSavedStateRegistry() return remember { object : ViewModelStoreOwner, SavedStateRegistryOwner { override val viewModelStore: ViewModelStore = viewModelStore override val savedStateRegistry: SavedStateRegistry = savedStateRegistry } }.also { owner -> DisposableEffect(Unit) { onDispose { owner.viewModelStore.clear() } } } }
步骤2:在弹窗Composable中使用自定义ViewModelStoreOwner
在每个底部弹窗的Composable中,通过上面的函数获取独立的ViewModelStoreOwner,再传入hiltViewModel():
when(bottomSheetType){ BottomSheetType.TYPE1 -> { val viewModelOwner = rememberBottomSheetViewModelStoreOwner() Screen1(hiltViewModel<Type1ViewModel>(viewModelStoreOwner = viewModelOwner)) } BottomSheetType.TYPE2 -> { val viewModelOwner = rememberBottomSheetViewModelStoreOwner() Screen2(hiltViewModel<Type2ViewModel>(viewModelStoreOwner = viewModelOwner)) } BottomSheetType.TYPE3 -> { val viewModelOwner = rememberBottomSheetViewModelStoreOwner() Screen3(hiltViewModel<Type3ViewModel>(viewModelStoreOwner = viewModelOwner)) } // 其他弹窗类型同理 }
关键注意事项
- 确保弹窗的显示逻辑是通过
if判断实现的:当弹窗隐藏时,对应的Composable会从Composition中移除,触发DisposableEffect的onDispose回调,清理ViewModelStore,ViewModel随之销毁。 - 若需要保存ViewModel的状态,弹窗的显示状态建议用
rememberSaveable管理,这样rememberSavedStateRegistry能正常工作。 - Hilt的依赖注入逻辑不受影响,
hiltViewModel()会自动使用Hilt生成的ViewModelFactory创建实例。
内容的提问来源于stack exchange,提问作者Ivan
相关产品推荐
相关产品推荐

