17

我想将 LiveData 与 Kotlin 一起使用,并且具有不应为空的值。你如何处理这个问题?也许是 LiveData 的包装器?在这里寻找好的模式..例如:

class NetworkDefinitionProvider : MutableLiveData<NetworkDefinition>() {
    val allDefinitions = mutableListOf(RinkebyNetworkDefinition(), MainnetNetworkDefinition(), RopstenNetworkDefinition())

    init {
        value = allDefinitions.first()
    }

    fun setCurrent(value: NetworkDefinition) {
        setValue(value)
    }
}

我知道访问时 value 不会为 null - 但我总是必须检查 null 或周围有这些丑陋的!!。

4

8 回答 8

13

我对The Lucky Coder 的回答几乎没有改进。这个实现根本不能接受空值。

class NonNullMutableLiveData<T: Any>(initValue: T): MutableLiveData<T>() {

    init {
        value = initValue
    }

    override fun getValue(): T {
        return super.getValue()!!
    }

    override fun setValue(value: T) {
        super.setValue(value)
    }

    fun observe(owner: LifecycleOwner, body: (T) -> Unit) {
        observe(owner, Observer<T> { t -> body(t!!) })
    }

    override fun postValue(value: T) {
        super.postValue(value)
    }    
}
于 2018-03-31T20:30:09.300 回答
9

我不知道这是否是最好的解决方案,但这就是我想出的和我使用的:

class NonNullLiveData<T>(private val defaultValue: T) : MutableLiveData<T>() {

    override fun getValue(): T = super.getValue() ?: defaultValue

    fun observe(owner: LifecycleOwner, body: (T) -> Unit) {
        observe(owner, Observer<T> {
            body(it ?: defaultValue)
        })
    }
}

创建字段:

val string = NonNullLiveData("")

并观察它:

viewModel.string.observe(this) {
    // Do someting with the data
}
于 2018-03-16T15:53:53.593 回答
3

您可以为 LifecycleOwner 创建一个扩展

fun <T> LifecycleOwner.observe(liveData: LiveData<T?>, lambda: (T) -> Unit) {
    liveData.observe(this, Observer { if (it != null) lambda(it) })
}

然后在您的片段/活动中

observe(liveData) { ... }
于 2018-04-14T21:04:58.843 回答
2

你可以这样做

normalLiveData
  .nonNull()
  .observe(this, { result -> 
    // result is non null now
  })

有一篇关于它的文章。https://medium.com/@henrytao/nonnull-livedata-with-kotlin-extension-26963ffd0333

于 2018-04-21T15:41:44.550 回答
0

这是我的解决方案。

class NotNullLiveData<T : Any>
constructor(private val default: T) : MediatorLiveData<T>() {
    override fun getValue(): T {
        return super.getValue() ?: default
    }

    override fun setValue(value: T) {
        super.setValue(value)
    }
}

@MainThread
fun <T : Any> mutableLiveDataOfNotNull(initValue: T): NotNullLiveData<T> {
    val liveData = NotNullLiveData(initValue)
    liveData.value = initValue
    return liveData
}

@MainThread
fun <T> mutableLiveDataOf(initValue: T): MutableLiveData<T> {
    val liveData = MutableLiveData<T>()
    liveData.value = initValue
    return liveData
}


fun <T : Any> LiveData<T?>.toNotNull(default: T): NotNullLiveData<T> {
    val result = NotNullLiveData(default)
    result.addSource(this) {
        result.value = it ?: default
    }
    return result
}
于 2018-11-08T10:04:48.120 回答
0

我真的很喜欢The Lucky Coder的回答。关于尝试设置空值的危险,我认为我们应该为此抛出异常(类似于大卫惠特曼所指的):

class NonNullLiveData<T>(private val defaultValue: T) : MutableLiveData<T>() {

override fun getValue(): T = super.getValue() ?: defaultValue

override fun setValue(value: T) {
    if(value != null) {
        super.setValue(value)
    }
    else throw IllegalArgumentException("Cannot set a null value to this Type. Use normal MutableLiveData instead for that.")
}

override fun postValue(value: T) {
    if(value != null) {
        super.postValue(value)
    }
    else throw IllegalArgumentException("Cannot post a null value to this Type. Use normal MutableLiveData instead for that.")
}

fun observe(owner: LifecycleOwner, body: (T) -> Unit) {
    observe(owner, Observer<T> {
        body(it ?: defaultValue)
    })
}

}

现在 MutableLiveData 中的值将永远不会为空,因此该类不会以不符合预期的方式使用。

于 2019-12-21T14:51:54.300 回答
0

使用字符串时,使用这种方式很简单:

val someLiveData = MutableLiveData<String>()
...
someLiveData.value.orEmpty()

如果设置或空字符串而不是null.

于 2019-03-22T08:47:15.180 回答
-1

我创建了一个扩展属性。它不是超级漂亮,但它非常简单。

val <T> LiveData<T>.valueNN
    get() = this.value!!

用法

spinner.loading = myLiveData.valueNN.homeState.loading

我不赞成将“NN”附加为一个好的命名约定,但这超出了问题的范围:)

于 2018-01-25T19:22:55.483 回答