TL;DR
我认为flatMap
和switchMap
组合可能无法正确终止流,因此会发生UndeliverableException
。我该怎么解决这个问题?
结构
我正在RxKotlin(RxJava 3(中制作一个有点复杂的流——与flatMap
和switchMap
相结合——如下所示:
someObservable
.flatMapMaybe {
if (matchCondition(it)) Maybe.just(it)
else Maybe.never()
}.flatMapSingle {
procedureMiddle(it) // Inconsistent-time-consuming Single
}.switchMap {
procedureLater(it)
}.doOnError {
dealWithError(e)
}.retry()
.subscribeBy(
// ...
)
flatMapSingle
中的procedureMiddle
最终有机会返回Error。
例外情况
结果表明,有时procedureMiddle
的错误可能会跳出结构,retry
不会忽略,doOnError
:中的dealWithError
也不会处理
W/System.err: io.reactivex.rxjava3.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | my.custom.app.CustomException
// traces indicates that the Exception is thrown from inside procedureMiddle
问题
事实上,UndeliverableException
并没有真正导致崩溃,但它对我来说有点烦人——尤其是它看起来像是我需要处理的情况。然而,我认为结构写得正确吗?所以我的问题是:
switchMap
真的(正确地(终止了flatMap
的最后一个流吗?(可用于预防UndeliverableException
?(- 如果是,我应该在代码的哪一部分进行调整?如果不是这样的话,我该如何防止我的结构出现异常?(我想在
procedureMiddle
之后加入procedureLater
,只保留最新的(
任何建议或解释都会有所帮助。
RxJava2官方文档解释了一些关于UndeliverableException
:的内容
UndeliverableException
:包装由于Subscriber
/Observer
的生命周期限制而无法交付的原始异常。
所以,实际上,这并不意味着你的代码(直接(有任何问题。它只是提醒您,某些流在您结束/取消/处理它们之后仍然会抛出错误。
关于问题:
switchMap
真的(正确地(终止了flatMap
的最后一个流吗?(可用于防止UndeliverableException
?(
- 是的,它终止了最后一个流
- 第
UndeliverableException
号仍然会发生。因为它终止了最后一个流,所以如果最后一个数据流抛出错误,则该错误将被包装并作为UndeliverableException
抛出
如果是,我应该调整代码的哪一部分?如果不是这样的话,我该如何防止我的结构出现异常?
您不需要调整代码,也不需要阻止UndeliverableException
,因为它总是有机会在处理/取消/结束任何流时出现(手动甚至自动(
我建议忽略它:
RxJavaPlugins.setErrorHandler {
if (it is UndeliverableException) {
// This happens when throwable comes out AFTER subscription is canceled or disposed.
// Not what we care about as it is likely disposed by user or system.
Log.d(
"Application", "UndeliverableException: ignored.n" +
"$it: problem ${it.cause} / ${it.cause?.message}n" +
"at ${it.cause?.stackTraceToString()}"
)
return@setErrorHandler
}
// other Exceptions: do some report
}