首页 > 解决方案 > Android 的 MutableLiveData 应该只使用可为空的对象吗?

问题描述

我的简化代码是:

class MyViewModel : ViewModel() {
    private val myLiveData: MutableLiveData<MyObject> = MutableLiveData<MyObject>(MyObject())
    val myObject: MutableLiveData<MyObject>
        get() = myLiveData

    fun addItem(item: MyItem) {
        val value = myLiveData.value // value is of nullable type MyObject?
        // MyObject contains a list of other objects
        (value?.myList as MutableList).add(item)
        myLiveData.value = value!! // Here I get a IDE warning or error
    }
}

如果我在第 9 行留下非空运算符 (!!),Android Studio 会给我一个警告:

Unnecessary non-null assertion (!!) on a non-null receiver of type MyObject

如果我在第 9 行删除非空运算符 (!!),Android Studio 会给我一个错误:

Expected non-nullable value

在 Kotlin 中处理这个问题的正确方法是什么?如果我MyObject?在第 2 行和第 3 行使用可空值,Android Studio 似乎喜欢它,但我真的不打算让该数据为空……MutableLiveData应该总是可空的吗?

标签: androidkotlinandroid-livedatamutablelivedatanon-nullable

解决方案


LiveData确实是要观察的——当你调用observe它并传递一个处理函数时,只有当 LiveData 有一个值(当前值或新值)时才会调用该函数。因为您的 LiveData 拥有非 nullMyObject类型,所以观察者函数只会被赋予非 null MyObjects。

但如果你在戳它的value属性——那就不一样了!即使您MyObject在其构造函数中提供了初始值,您也不必这样做 - 所以LiveDatas 有时可以为。如果您尝试观察它,则在设置值之前不会调用观察者。如果您尝试查看它value,它将是null,因为 LiveData 中还没有任何内容。这并不意味着它向观察者提供空值,只是它还没有存储值!

所以value总是可以为空的,即使LiveData持有的类型是非空的。你有点在幕后偷看。你真的有两个选择:

  • 以通常的方式()使用空安全的东西value?.let { ... },不要担心,因为你知道那里总会有一个值,因为你已经在构造函数中设置了一个(这是最安全的选项)
  • 使用!!,因为这似乎是少数安全的情况之一 - 你知道它不会为空

我个人认为整件事有点乱,LiveData有……怪癖,但在这种情况下你没问题 - 我只是想解释一下发生了什么!


此外,您的公共类型应该是LiveData<MyObject>而不是MutableLiveData<MyObject>- 您的内部副本需要是可变的(以便您可以更新它),但您公开的引用应该是不可变LiveData类型,因此用户无法设置它并且必须通过您的 setter 函数. 只需更改类型:

val myObject: LiveData<MyObject>
        get() = myLiveData

他们会把它看作是LiveData他们不能乱用的标准,而不是可变的子类


推荐阅读