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#1LiveData 的正确用法。

首先,LiveData 不负责缓存,它只是 LifeCycleAware Observable,假设缓存是在 ViewModel 完成的,当您的 activity 由于任何配置更改而重新创建时, android 将尝试检索 ViewModel 的现有实例,如果找到则它的状态和数据将按原样保留,否则它将创建 ViewModel.

的新实例

其次,在 repository 中使用 LiveData 在很多层面上都是一个坏主意,存储库实例由 ViewModel 持有,而 LiveData 是 [=30= 的一部分] 使存储库依赖于 Android 框架的框架,从而在单元测试中产生问题。始终仅在 ViewModels.

中使用 LiveData