ViewModel 是如何缓存 LiveData 的?
How does ViewModel cache LiveData?
我在 Google 的 Codelabs 和其他来源的不同示例项目中看到了以下所有场景,但不完全理解从哪里检索 LiveData 对象的值。
场景 1 - 当前理解:
根据https://developer.android.com/.../viewmodel,使用 ViewModel 的一个原因是 store/cache UI 相关数据,我想在相应的 UI 重建后重新使用这些数据配置更改后。
给定以下简化的 ViewModel 和 Repository:在第一次调用 updateName() 后,_currentName 的 LiveData 对象包含一个 String。如果 UI 然后在屏幕旋转后重建,需要显示当前名称的视图通过观察 currentName 请求它,而 currentName 又 returns 包含在字段中的 LiveData 对象的值_currentName 属性。我说得对吗?
ViewModel
class NamesViewModel(): ViewModel() {
private val respository = NamesRepository()
private val _currentName: MutableLivedata<String?> = MutableLiveData(null)
val currentName: LiveData<String?> get() = this._currentName
...
// Called as UI event listener.
fun updateName() {
this._currentName.value = this.repository.updateName()
}
}
存储库
class NamesRepository() {
fun updateName(): String {
val nextName: String
...
return nextName
}
}
场景二:
如果 UI 在以下情况下屏幕旋转后重建会怎样? ViewModel 中的 _currentName 'observes' 存储库中的 currentName,但它仍然是一个 属性,因此在其字段中存储了自己的 LiveData 对象。然后,当视图从 ViewModel 请求 currentName 时,会从 ViewModel 的 _currentName 属性 字段中包含的 LiveData 对象中检索该值。这是正确的吗?
ViewModel
class NamesViewModel(): ViewModel() {
private val respository = NamesRepository()
private val _currentName: LiveData<String?> = this.repository.currentName
val currentName: LiveData<String?> get() = this._currentName
...
// Called as UI event listener.
fun updateName() {
this.repository.updateName()
}
}
存储库
class NamesRepository() {
private val _currentName: MutableLivedata<String?> = MutableLiveData(null)
val currentName: LiveData<String?> get() = this._currentName
fun updateName() {
val nextName: String
...
this._currentName.value = nextName
}
}
场景三:
在下面的场景中,如果 UI 正在重建并且视图从 ViewModel 请求 currentNam,请求的值存储在哪里?我目前的理解是,currentName 返回到存储库中 属性 _currentName 的字段。这是否违背了 ViewModel 存储相关 UI 数据以便在配置更改后重新使用的想法?在下面的例子中,从存储库而不是 viewModel 中检索值可能没有问题,但是如果存储库本身直接从来自 Room 数据库的 LiveData 对象检索值呢?难道每次视图从 viewModel 请求 _currentName 时都会进行数据库访问吗?
我希望有人能更清楚地说明情况,以便了解如何以正确的方式在 viewModel 中缓存 UI 相关数据(或者至少了解哪些是不正确的方式)。
ViewModel
class NamesViewModel(): ViewModel() {
private val respository = NamesRepository()
val currentName: LiveData<String?> get() = this.repository.currentName
...
// Called as UI event listener.
fun updateName() {
this.repository.updateName()
}
}
存储库
class NamesRepository() {
private val _currentName: MutableLivedata<String?> = MutableLiveData(null)
val currentName: LiveData<String?> get() = this._currentName
fun updateName() {
val nextName: String
...
this._currentName.value = nextName
}
}
回答你的问题 scenario#1
是 LiveData
的正确用法。
首先,LiveData
不负责缓存,它只是 LifeCycleAware Observable,假设缓存是在 ViewModel
完成的,当您的 activity
由于任何配置更改而重新创建时, android 将尝试检索 ViewModel
的现有实例,如果找到则它的状态和数据将按原样保留,否则它将创建 ViewModel
.
的新实例
其次,在 repository
中使用 LiveData
在很多层面上都是一个坏主意,存储库实例由 ViewModel
持有,而 LiveData
是 [=30= 的一部分] 使存储库依赖于 Android 框架的框架,从而在单元测试中产生问题。始终仅在 ViewModels
.
中使用 LiveData
我在 Google 的 Codelabs 和其他来源的不同示例项目中看到了以下所有场景,但不完全理解从哪里检索 LiveData 对象的值。
场景 1 - 当前理解:
根据https://developer.android.com/.../viewmodel,使用 ViewModel 的一个原因是 store/cache UI 相关数据,我想在相应的 UI 重建后重新使用这些数据配置更改后。
给定以下简化的 ViewModel 和 Repository:在第一次调用 updateName() 后,_currentName 的 LiveData 对象包含一个 String。如果 UI 然后在屏幕旋转后重建,需要显示当前名称的视图通过观察 currentName 请求它,而 currentName 又 returns 包含在字段中的 LiveData 对象的值_currentName 属性。我说得对吗?
ViewModel
class NamesViewModel(): ViewModel() {
private val respository = NamesRepository()
private val _currentName: MutableLivedata<String?> = MutableLiveData(null)
val currentName: LiveData<String?> get() = this._currentName
...
// Called as UI event listener.
fun updateName() {
this._currentName.value = this.repository.updateName()
}
}
存储库
class NamesRepository() {
fun updateName(): String {
val nextName: String
...
return nextName
}
}
场景二:
如果 UI 在以下情况下屏幕旋转后重建会怎样? ViewModel 中的 _currentName 'observes' 存储库中的 currentName,但它仍然是一个 属性,因此在其字段中存储了自己的 LiveData 对象。然后,当视图从 ViewModel 请求 currentName 时,会从 ViewModel 的 _currentName 属性 字段中包含的 LiveData 对象中检索该值。这是正确的吗?
ViewModel
class NamesViewModel(): ViewModel() {
private val respository = NamesRepository()
private val _currentName: LiveData<String?> = this.repository.currentName
val currentName: LiveData<String?> get() = this._currentName
...
// Called as UI event listener.
fun updateName() {
this.repository.updateName()
}
}
存储库
class NamesRepository() {
private val _currentName: MutableLivedata<String?> = MutableLiveData(null)
val currentName: LiveData<String?> get() = this._currentName
fun updateName() {
val nextName: String
...
this._currentName.value = nextName
}
}
场景三:
在下面的场景中,如果 UI 正在重建并且视图从 ViewModel 请求 currentNam,请求的值存储在哪里?我目前的理解是,currentName 返回到存储库中 属性 _currentName 的字段。这是否违背了 ViewModel 存储相关 UI 数据以便在配置更改后重新使用的想法?在下面的例子中,从存储库而不是 viewModel 中检索值可能没有问题,但是如果存储库本身直接从来自 Room 数据库的 LiveData 对象检索值呢?难道每次视图从 viewModel 请求 _currentName 时都会进行数据库访问吗?
我希望有人能更清楚地说明情况,以便了解如何以正确的方式在 viewModel 中缓存 UI 相关数据(或者至少了解哪些是不正确的方式)。
ViewModel
class NamesViewModel(): ViewModel() {
private val respository = NamesRepository()
val currentName: LiveData<String?> get() = this.repository.currentName
...
// Called as UI event listener.
fun updateName() {
this.repository.updateName()
}
}
存储库
class NamesRepository() {
private val _currentName: MutableLivedata<String?> = MutableLiveData(null)
val currentName: LiveData<String?> get() = this._currentName
fun updateName() {
val nextName: String
...
this._currentName.value = nextName
}
}
回答你的问题 scenario#1
是 LiveData
的正确用法。
首先,LiveData
不负责缓存,它只是 LifeCycleAware Observable,假设缓存是在 ViewModel
完成的,当您的 activity
由于任何配置更改而重新创建时, android 将尝试检索 ViewModel
的现有实例,如果找到则它的状态和数据将按原样保留,否则它将创建 ViewModel
.
其次,在 repository
中使用 LiveData
在很多层面上都是一个坏主意,存储库实例由 ViewModel
持有,而 LiveData
是 [=30= 的一部分] 使存储库依赖于 Android 框架的框架,从而在单元测试中产生问题。始终仅在 ViewModels
.
LiveData