【问题标题】:Kotlin Coroutines remove exception handler from scopeKotlin Coroutines 从作用域中移除异常处理程序
【发布时间】:2020-03-24 08:51:38
【问题描述】:

在下面的代码中,我正在获取一些数据。如果抛出错误/异常,我希望异常处理程序捕获它。完成获取后,我将使用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 之前删除异常处理程序?还是我必须引入一个新范围?

【问题讨论】:

    标签: kotlin-coroutines


    【解决方案1】:

    您似乎误解了协程异常处理程序的用途。它是 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) }
    }
    

    【讨论】:

    • 所以在这种情况下的解决方案只是用 try catch 包装 await 调用。处理 catch 部分中的错误并保留异常处理程序以进行日志记录,因为异步重新抛出异常?
    • 您应该通过将async 任务本身捕获到内部来防止它失败。
    • 好酷明白了!但是,如果计划并行处理多个异步,那么我确实需要包装所有 await 而不是尝试捕获每个异步
    • 如果你有多个异步调用,它们都应该在 coroutineScope { ... } 中,然后你应该将整个 coroutineScope 包装在一个 try-catch 中。
    猜你喜欢
    • 2020-03-01
    • 1970-01-01
    • 2019-04-13
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多