我在Google的Codelabs和其他来源的不同示例项目中看到了以下所有场景,并且不完全理解LiveData对象的值是从哪里检索的。
场景1 -当前理解:
根据https://developer.android.com/.../viewmodel使用ViewModel的一个原因是存储/缓存与UI相关的数据,我想在配置更改后重建相应的UI后重用。
给定以下简化的ViewModel和Repository:在updateName()第一次被调用之后,_currentName的LiveData对象包含一个String。如果在屏幕旋转之后重新构建UI,则需要显示当前名称的视图通过观察currentName来请求它,而currentName反过来返回包含在_currentName属性字段中的LiveData对象的值。我说的对吗?
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
}
}
场景2:
在以下情况下,如果UI在屏幕旋转后重建会发生什么?ViewModel中的_currentName '观察'存储库中的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
}
}
场景3:
在下面的场景中,如果UI被重新构建,并且视图从ViewModel请求currentNam,那么请求的值存储在哪里?我目前的理解是,currentName落回到存储库中属性_currentName的字段。这是否违背了ViewModel存储配置更改后重用的相关UI数据的想法?在下面的例子中,从存储库而不是从viewModel中检索值可能没有问题,但是如果存储库本身直接从来自Room数据库的LiveData对象中检索值呢?每次视图从viewModel请求_currentName时,不会发生数据库访问吗?
我希望有人能澄清更多的情况,以了解如何缓存UI相关的数据在viewModel正确的方式(或至少了解什么是不正确的方式)。
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
持有,这使得存储库依赖于Android框架,从而在单元测试中产生问题。只在ViewModels
中使用LiveData
。