剥开 ViewModel 的面纱,彻底理解其实现原理
2023-12-02 20:14:31
配置更改中的数据持久性:使用 ViewModel
在 Android 开发中,配置更改 是不可避免的。它们包括屏幕旋转、语言切换,甚至系统更新等事件。这些更改会导致 Activity 和 Fragment 被销毁并重新创建,从而可能导致临时数据丢失。
为了应对这一挑战,ViewModel 应运而生。ViewModel 是一种 生命周期感知组件 ,可以跨越配置更改而持久存在。这使其成为存储临时数据的理想场所,确保在配置更改期间数据不会丢失。
ViewModel 的生命周期
ViewModel 的生命周期与它关联的 Activity 或 Fragment 无关。当 Activity 或 Fragment 被销毁时,ViewModel 仍然存在。当 Activity 或 Fragment 重新创建时,它们会与现有的 ViewModel 重新关联。这种持久性确保数据在配置更改后仍然可用。
数据存储
ViewModel 本质上是一个数据持有者 。它提供了一个可扩展的存储库,用于存储 可观察数据 和 状态 。通过使用 LiveData
和 MutableLiveData
等数据类,ViewModel 可以确保数据在所有观察者之间保持同步。
使用 ViewModel
使用 ViewModel 很简单,只需以下几步:
- 创建一个 ViewModel 类,继承自
androidx.lifecycle.ViewModel
。 - 在 Activity 或 Fragment 中,使用
ViewModelProviders
获取 ViewModel 实例。 - 将临时数据存储在 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 的行为。