[英]Nullability and LiveData with Kotlin
我想將 LiveData 與 Kotlin 一起使用,並且具有不應為 null 的值。 你如何處理這個問題? 也許是 LiveData 的包裝器? 在這里搜索好的模式.. 舉個例子:
class NetworkDefinitionProvider : MutableLiveData<NetworkDefinition>() {
val allDefinitions = mutableListOf(RinkebyNetworkDefinition(), MainnetNetworkDefinition(), RopstenNetworkDefinition())
init {
value = allDefinitions.first()
}
fun setCurrent(value: NetworkDefinition) {
setValue(value)
}
}
我知道訪問時 value 不會為 null - 但我將始終必須檢查 null 或有這些丑陋的 !! 。
我幾乎沒有改進答案幸運編碼器。 這個實現根本不能接受空值。
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)
}
}
我不知道這是否是最好的解決方案,但這是我想出的和我使用的:
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
}
您可以為 LifecycleOwner 創建擴展
fun <T> LifecycleOwner.observe(liveData: LiveData<T?>, lambda: (T) -> Unit) {
liveData.observe(this, Observer { if (it != null) lambda(it) })
}
然后在你的片段/活動中
observe(liveData) { ... }
你可以這樣做
normalLiveData
.nonNull()
.observe(this, { result ->
// result is non null now
})
有一篇關於它的文章。 https://medium.com/@henrytao/nonnull-livedata-with-kotlin-extension-26963ffd0333
這是我的解決方案。
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
}
通過使用這種方式使用字符串很簡單:
val someLiveData = MutableLiveData<String>()
...
someLiveData.value.orEmpty()
如果設置或空字符串而不是null
,您將獲得實際值。
我真的很喜歡Lucky Coder的回答。 關於嘗試設置空值的危險,我認為我們應該為此拋出一個異常(類似於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 中的值永遠不會為空,因此該類不會以非預期的方式使用。
我創建了一個擴展屬性。 這不是超級漂亮,但它是非常簡單的。
val <T> LiveData<T>.valueNN
get() = this.value!!
用法
spinner.loading = myLiveData.valueNN.homeState.loading
我不認為附加“NN”是一個好的命名約定,但這超出了問題的范圍:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.