【问题标题】:How does ViewModel cache LiveData?ViewModel 如何缓存 LiveData?
【发布时间】:2021-02-02 12:41:08
【问题描述】:

我在来自 Google 的 Codelabs 和其他来源的不同示例项目中看到了以下所有场景,并且不完全了解从哪里检索 LiveData 对象的值。

场景 1 - 当前理解:

根据https://developer.android.com/.../viewmodel 的说法,使用 ViewModel 的一个原因是存储/缓存与 UI 相关的数据,这些数据在配置更改后重建相应的 UI 后我想重新使用。

给定以下简化的 ViewModel 和 Repository:第一次调用 updateName() 后,_currentName 的 LiveData 对象包含一个字符串。如果在屏幕旋转后重新构建 UI,则需要显示当前名称的视图通过观察 currentName 来请求它,而 currentName 又返回包含在 _currentName 属性字段中的 LiveData 对象的值。我说的对吗?

视图模型

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 对象中检索该值。这是正确的吗?

视图模型

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 时不会发生数据库访问吗?

我希望有人能更清楚地说明情况,以便了解如何以正确的方式在 viewModel 中缓存 UI 相关数据(或至少了解哪些是不正确的方式)。

视图模型

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
    }
}

【问题讨论】:

    标签: android kotlin viewmodel android-livedata


    【解决方案1】:

    回答您的问题scenario#1LiveData 的正确用法。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-16
      相关资源
      最近更新 更多