在下面的代码中,我正在获取一些数据。如果抛出了错误/异常,我希望异常处理程序捕捉到它。一旦完成提取,我将使用LiveData
将结果发布给观察的人。
我试图实现的是,一旦我发布结果,异常处理程序就会完成它的工作。这意味着,如果处理结果的观察者也抛出异常,我不希望协程异常处理程序捕获它(下面的代码就是这样(。
fun loadPrerequisites(resultObserver: MutableLiveData<PrerequisiteDataHolder?>) {
val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
resultObserver.postValue(null)
}
scope.launch(Dispatchers.IO + exceptionHandler) {
val deferredCreationScheme = async {
fetchCreationScheme()
}
val creationScheme = deferredCreationScheme.await()
//TODO remove exception handler at this stage?
resultObserver.postValue(PrerequisiteDataHolder(creationScheme))
}
}
在将结果发布到LiveData之前,是否有方法删除异常处理程序?或者我必须引入一个新的范围吗?
您似乎误解了协程异常处理程序的用途。它是Java中uncaughtExceptionExceptionHandler
的协同程序等价物,其目的是通知您已经破坏其协同程序的异常。您似乎希望使用它来实现业务逻辑级别的异常处理。
协程异常处理程序不能替代try-catch块,后者是您在案例中应该使用的。
我认为你的代码一开始就不需要async
,我相信这就是你真正需要的:
scope.launch(Dispatchers.IO) {
resultObserver.postValue(
try {
PrerequisiteDataHolder(fetchCreationScheme())
} catch (e: Exception) {
null
}
)
}
我通常会为这样的代码使用一个助手函数:
inline fun <T> tryOrNull(block: () -> T) = try {
block()
} catch (t: Throwable) {
null
}
然后你的代码变成
scope.launch(Dispatchers.IO) {
tryOrNull { PrerequisiteDataHolder(fetchCreationScheme()) }
.also { resultObserver.postValue(it) }
}