返回

ViewModel的限制,及其在销毁重建场景下的解决之道

Android

前言

ViewModel,作为Jetpack中举足轻重的部分,相信大家已经很熟悉了。而今天重提是因为要为自己的“愚蠢”买单...之前的自己一直想当然的以为ViewModel可以解决Activity销毁重建的问题(但是,这是一个错误的认知)。直到踩到了坑,才仔细的想了想...

ViewModel作为数据持有者,其生命周期与Activity并不绑定,它在Activity销毁后依然存在,从而避免了数据丢失的问题。但是,当Activity销毁重建后,ViewModel会被重新创建,之前持有的数据也会随之丢失。

那么,如何解决这个问题呢?本文将针对ViewModel的局限性进行深入探讨,并介绍一种有效的解决方案——SavedStateHandle。

ViewModel的局限性

ViewModel的作用是持有数据,并提供数据共享和生命周期管理的功能。它与Activity的生命周期解耦,在Activity销毁后依然存在。但是,ViewModel有一个局限性,就是当Activity销毁重建后,ViewModel会被重新创建,之前持有的数据也会随之丢失。

这是因为ViewModel的生命周期与Activity生命周期不同。Activity销毁时,ViewModel不会被销毁,而是处于一种"inactive"的状态。当Activity重建时,ViewModel会被重新创建,并加载新的数据。

SavedStateHandle的解决方案

为了解决ViewModel的局限性,Jetpack提供了SavedStateHandle这个类。SavedStateHandle可以保存数据,并跨Activity销毁重建的过程。

SavedStateHandle的工作原理如下:

  1. 在ViewModel中创建SavedStateHandle实例。
  2. 使用SavedStateHandle保存数据。
  3. 在Activity重建时,ViewModel会重新创建,并从SavedStateHandle中恢复数据。

通过这种方式,即使Activity被销毁重建,ViewModel中保存的数据也不会丢失。

使用SavedStateHandle

使用SavedStateHandle非常简单,只需以下几步即可:

  1. 在ViewModel中创建SavedStateHandle实例:
class MyViewModel(savedStateHandle: SavedStateHandle) : ViewModel() {
    // ...
}
  1. 使用SavedStateHandle保存数据:
savedStateHandle["myData"] = myData
  1. 在Activity重建时,ViewModel会重新创建,并从SavedStateHandle中恢复数据:
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val myViewModel = ViewModelProvider(this).get(MyViewModel::class.java)
    val myData = myViewModel.savedStateHandle["myData"]
}

需要注意的是,SavedStateHandle保存的数据只会在Activity销毁重建时保留。如果Activity被完全退出,SavedStateHandle保存的数据也会丢失。

总结

ViewModel是Jetpack中一个非常有用的组件,它可以帮助我们管理数据,并解耦数据与Activity生命周期。但是,ViewModel也有其局限性,当Activity销毁重建时,ViewModel会被重新创建,之前持有的数据也会随之丢失。

为了解决这个局限性,Jetpack提供了SavedStateHandle这个类。SavedStateHandle可以保存数据,并跨Activity销毁重建的过程。通过使用SavedStateHandle,我们可以确保即使Activity被销毁重建,ViewModel中保存的数据也不会丢失。