我想将LiveData与Kotlin一起使用,并且值不应为null。你怎么处理这个?也许LiveData的包装?在这里寻找好的模式.. 举个例子:
class NetworkDefinitionProvider : MutableLiveData<NetworkDefinition>() {
val allDefinitions = mutableListOf(RinkebyNetworkDefinition(), MainnetNetworkDefinition(), RopstenNetworkDefinition())
init {
value = allDefinitions.first()
}
fun setCurrent(value: NetworkDefinition) {
setValue(value)
}
}
我知道访问时价值不会为空 - 但我总是要检查是否为空,或者让这些丑陋的东西出现。
答案 0 :(得分:9)
我很少改进answer幸运编码器。此实现根本不能接受空值。
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)
}
}
答案 1 :(得分:8)
我不知道这是否是最佳解决方案,但这是我提出的以及我使用的内容:
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
}
答案 2 :(得分:2)
您可以为LifecycleOwner
创建扩展程序fun <T> LifecycleOwner.observe(liveData: LiveData<T?>, lambda: (T) -> Unit) {
liveData.observe(this, Observer { if (it != null) lambda(it) })
}
然后在你的片段/活动中
observe(liveData) { ... }
答案 3 :(得分:1)
我创建了一个扩展属性。它并不是非常漂亮,但 非常简单。
val <T> LiveData<T>.valueNN
get() = this.value!!
用法
spinner.loading = myLiveData.valueNN.homeState.loading
我不会因为附加“NN”作为一个好的命名惯例而被出售,但这超出了问题的范围:)
答案 4 :(得分:1)
你可以这样做
normalLiveData
.nonNull()
.observe(this, { result ->
// result is non null now
})
有一篇关于它的文章。 https://medium.com/@henrytao/nonnull-livedata-with-kotlin-extension-26963ffd0333
答案 5 :(得分: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
}
答案 6 :(得分:0)
使用字符串的方法很简单:
val someLiveData = MutableLiveData<String>()
...
someLiveData.value.orEmpty()
如果设置了该值,您将获得实际值,或者使用空字符串代替null
。
答案 7 :(得分:0)
我真的很喜欢The Lucky Coder的答案。关于尝试设置null值的危险,我认为我们应该为此抛出一个异常(类似于David Whitman所指):
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中的值将永远不会为null,因此不会以非预期的方式使用该类。