簡體   English   中英

Kotlin 的可空性和 LiveData

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM