如何在 Kotlin 自定义 getter 中抛出异常并从 运行 停止应用程序?

How to throw am Exception in Kotlin custom getter and stop the app from running?

我想验证我的 MediatorLiveData 是否设置了实际值:

val entries = MediatorLiveData<List<Entry>>()
    get() = when {
        entries.value == null -> throw IllegalStateException("wah")
        else -> field
    }

我没有遇到编译器错误,但是当 运行 代码出现 Whosebug 时,因为 getter 在 (entries.value == null) 路径中被一遍又一遍地调用。

1.如何在自定义 getter 中抛出异常并从 运行

停止应用程序

更新最终解决方案: 感谢@zapl 和@kcoppock 的回答。他们都帮助我找到了最终的解决方案:

private lateinit var _entries: LiveData<List<Entry>>
val entries = MediatorLiveData<List<Entry>>()
    get() = when {
        !::_entries.isInitialized -> throw IllegalStateException("EntryListViewModel was not initialized. Please call init() first.")
        else -> field
    }

fun init() {
    _entries = getEntries(false)
    entries.addSource(_entries) { entries.value = it.orEmpty() }
}

fun refreshEntries() {
    entries.removeSource(_entries)
    _entries = getEntries(true)
    entries.addSource(_entries) { entries.value = it.orEmpty() }
}

我还从另一个来源了解到 .isInitialized 用于 lateinit vars,这正是我所需要的。优雅地回退到空列表也是个好主意。

我会做的是保持 LiveData 私有,并为选中的 属性:

提供一个单独的访问器
private val _entries = MediatorLiveData<List<Entry>>()
val entries: List<Entry>
    get() = _entries.value!!

更好的是,除非您明确希望在这种情况下崩溃,否则您可以 return 一个空列表:

private val _entries = MediatorLiveData<List<Entry>>()
val entries: List<Entry>
    get() = _entries.value.orEmpty()

也就是说,LiveData 的要点是使用观察者,因此您只有在发布值时才会得到更新。

编辑:如果您的目标是强制初始值,您可以创建一个子类来强制执行此操作:

class NonNullMediatorLiveData<T>(initialValue: T) : MediatorLiveData<T>() {
    init { value = initialValue }

    override fun getValue(): T = super.getValue()!!

    override fun setValue(value: T) {
        // assert since the parent is defined in Java
        super.setValue(value!!)
    }
}