如何在 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!!)
}
}
我想验证我的 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!!)
}
}