在我的项目中,我有一个启动屏幕,当它显示时,我的应用程序从服务器加载一些启动数据,加载数据后显示另一个屏幕。 对于启动屏幕,我创建了一个 ViewModel,但它始终保留在内存中。如何正确销毁?
谢谢您的帮助!
@HiltViewModel
class SplashViewModel @Inject constructor (private val repository: Repository) {
....
}
@Composable
fun SplashScreen(vm: SplashViewModel) {
...
}
@Composable
fun Navigate() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "splash") {
composable("splash") {
SplashScreen(vm = hiltViewModel())
}
composable("main") {
MainScreen(...) // When shows MainScreen, SplashViewModel object still is in memory
}
}
}
您的视图模型保留在内存中,因为您的启动屏幕是您的根目的地,因此它始终作为底部条目保留在堆栈中。
如果您希望在离开启动屏幕时自动销毁启动视图模型,则应在导航到主屏幕时使用
popUpTo
将其从后台弹出。
您可以考虑的另一个选择是将主屏幕设为根目标,然后从该屏幕导航到启动应用程序(如果您是全新启动应用程序)。
使用
hiltViewModel
并将视图模型的范围限定为导航图目标,将确保视图模型在用户离开该屏幕时被销毁,前提是它不在后台堆栈中。
据我所知,Android 并未明确支持它。但是,您可以在视图模型本身内部创建一个名为
onViewModelCleared()
的方法,并将 null 传递给所有可为 null 的对象,并将轻量级的内容传递给非 null 对象。
当您使用函数
viewModel<YourViewModel>()
或hiltViewModel<YourViewModel>()
创建ViewModel时,创建的ViewModel与本地ViewModelStoreOwner
的范围关联。
ViewModelStoreOwner
包含存储 ViewModel 的类 - ViewModelStore
,您可以在其中使用函数 clear()
删除存储在其中的所有模型。
当用户离开屏幕时销毁 ViewModel 的方法之一,您可以创建自己的
ViewModelStoreOwner
,将创建的 ViewModel 与其关联,并在离开屏幕内的可组合函数 viewModelStoreOwner.viewModelStore.clear()
中调用 DisposableEffect()
。
示例:
1.创建您自己的简单
ViewModelStoreOwner
:
val viewModelStoreOwnerScreenSplash = object : ViewModelStoreOwner {
override val viewModelStore: ViewModelStore = ViewModelStore()
}
2.使用
viewModel()
函数创建ViewModel时,在参数viewModelStoreOwnerScreenSplash
中传入viewModelStoreOwner
:
val viewModel = viewModel<ScreenSplashViewModel>(
initializer = {
ScreenSplashViewModel(Repository())
},
viewModelStoreOwner = viewModelStoreOwnerScreenSplash,
key = "ScreenSplashViewModel"
)
3.在可组合函数
viewModelStoreOwnerScreenSplash
中传递 ScreenSplash()
参数并在可组合函数 viewModelStoreOwner.viewModelStore.clear()
中调用 DisposableEffect()
:
@Composable
fun ScreenSplash(
viewModel: ScreenSplashViewModel,
viewModelStoreOwnerScreenSplash: ViewModelStoreOwner
) {
//Your code of screen
DisposableEffect(key1 = Unit, effect = {
onDispose {
//Code inside will work as the last thing after leaving the screen
viewModelStoreOwnerScreenSplash.viewModelStore.clear()
}
})
}
当用户离开
ScreenSplash
时,函数DispossableEffect()
将被调用,viewModel将被清除并销毁。