返回

剥开 ViewModel 的面纱,彻底理解其实现原理

Android

配置更改中的数据持久性:使用 ViewModel

在 Android 开发中,配置更改 是不可避免的。它们包括屏幕旋转、语言切换,甚至系统更新等事件。这些更改会导致 Activity 和 Fragment 被销毁并重新创建,从而可能导致临时数据丢失。

为了应对这一挑战,ViewModel 应运而生。ViewModel 是一种 生命周期感知组件 ,可以跨越配置更改而持久存在。这使其成为存储临时数据的理想场所,确保在配置更改期间数据不会丢失。

ViewModel 的生命周期

ViewModel 的生命周期与它关联的 Activity 或 Fragment 无关。当 Activity 或 Fragment 被销毁时,ViewModel 仍然存在。当 Activity 或 Fragment 重新创建时,它们会与现有的 ViewModel 重新关联。这种持久性确保数据在配置更改后仍然可用。

数据存储

ViewModel 本质上是一个数据持有者 。它提供了一个可扩展的存储库,用于存储 可观察数据状态 。通过使用 LiveDataMutableLiveData 等数据类,ViewModel 可以确保数据在所有观察者之间保持同步。

使用 ViewModel

使用 ViewModel 很简单,只需以下几步:

  1. 创建一个 ViewModel 类,继承自 androidx.lifecycle.ViewModel
  2. 在 Activity 或 Fragment 中,使用 ViewModelProviders 获取 ViewModel 实例。
  3. 将临时数据存储在 ViewModel 的可观察数据中。

以下是一个示例,演示如何在配置更改期间保留文本输入字段的值:

// ViewModel 类
class MyViewModel : ViewModel() {
    val textValue = MutableLiveData<String>()
}

// Activity 类
class MyActivity : Activity() {
    private val viewModel by lazy { ViewModelProviders.of(this).get(MyViewModel::class.java) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val editText = findViewById<EditText>(R.id.editText)
        viewModel.textValue.observe(this, Observer {
            editText.setText(it)
        })
    }
}

优势

使用 ViewModel 有许多好处:

  • 数据持久性: ViewModel 跨越配置更改而持久存在,保护数据免遭丢失。
  • 代码简化: ViewModel 消除了在 onSaveInstanceState()onRestoreInstanceState() 中手动保存和恢复数据的需要,简化了代码。
  • 可测试性: ViewModel 易于测试,因为它与 Activity 或 Fragment 的生命周期无关。

限制

尽管很有用,ViewModel 也有一些限制:

  • 内存消耗: ViewModel 在整个应用程序生命周期中都存在,因此可能会消耗额外的内存。
  • 数据范围: ViewModel 只能访问与它关联的 Activity 或 Fragment 的数据,无法访问其他组件(如应用程序级数据)的数据。

结论

ViewModel 是一个功能强大的工具,可以帮助我们在配置更改期间避免数据丢失。通过理解它的实现和使用方法,我们可以有效地利用 ViewModel 来提高应用程序的鲁棒性和可维护性。

常见问题解答

1. ViewModel 和 SavedInstanceState 有什么区别?

  • SavedInstanceState 在配置更改期间暂时存储数据,而 ViewModel 在应用程序生命周期内持久存储数据。
  • ViewModel 可以存储可观察数据,而 SavedInstanceState 只存储可序列化的对象。

2. ViewModel 什么时候被销毁?

  • ViewModel 仅在应用程序进程终止时销毁。
  • 当 Activity 或 Fragment 被销毁时,ViewModel 仍然存在。

3. ViewModel 可以访问 Activity 或 Fragment 的私有数据吗?

  • 否,ViewModel 无法直接访问 Activity 或 Fragment 的私有数据。
  • 应该使用数据绑定或其他间接方法来共享数据。

4. 我可以使用 ViewModel 存储大数据吗?

  • 可以,但建议将大型数据存储在其他地方,例如持久数据库或文件系统中。
  • ViewModel 旨在存储较小的、可观察的数据块。

5. 如何在测试中使用 ViewModel?

  • 创建一个虚拟的 ViewModel 存储库,允许在测试中注入 ViewModel 实例。
  • 使用 Mockito 或类似的库来模拟 ViewModel 的行为。