当用户离开屏幕时如何销毁ViewModel

问题描述 投票:0回答:3

在我的项目中,我有一个启动屏幕,当它显示时,我的应用程序从服务器加载一些启动数据,加载数据后显示另一个屏幕。 对于启动屏幕,我创建了一个 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 
      }
   }
}
android android-jetpack android-jetpack-compose
3个回答
5
投票

您的视图模型保留在内存中,因为您的启动屏幕是您的根目的地,因此它始终作为底部条目保留在堆栈中。

如果您希望在离开启动屏幕时自动销毁启动视图模型,则应在导航到主屏幕时使用

popUpTo
将其从后台弹出。

您可以考虑的另一个选择是将主屏幕设为根目标,然后从该屏幕导航到启动应用程序(如果您是全新启动应用程序)。

使用

hiltViewModel
并将视图模型的范围限定为导航图目标,将确保视图模型在用户离开该屏幕时被销毁,前提是它不在后台堆栈中。


0
投票

据我所知,Android 并未明确支持它。但是,您可以在视图模型本身内部创建一个名为

onViewModelCleared()
的方法,并将 null 传递给所有可为 null 的对象,并将轻量级的内容传递给非 null 对象。


0
投票

当您使用函数

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将被清除并销毁。

© www.soinside.com 2019 - 2024. All rights reserved.