InterruptedException 没有在 RxJava onError 回调中捕获?
InterruptedException not caught on RxJava onError callback?
下面我有一个简单的代码
compositeDisposable.add(Observable.create<Int> { Thread.sleep(1000) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({}, {Log.d("Track", it.localizedMessage)}, {}))
Handler().postDelayed({compositeDisposable.clear()}, 100)
故意使用Thread.sleep(1000)
,就是为了触发InterruptedException
。我故意延迟 100 毫秒,以确保链中的睡眠已经开始,并将其处理掉。
(注意,我知道使用 Thread.sleep
不是首选。我只是编写这段代码来测试和理解为什么 onError
在这种情况下没有被调用,以及如何防止无需在 RxJava 链中使用 try-catch 即可优雅地崩溃)
当时,当它被触发时,错误不是 onError
的原因(即没有达到 Log
。而是抛出以下错误并使应用程序崩溃。
io.reactivex.exceptions.UndeliverableException: java.lang.InterruptedException
at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:366)
at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.onError(ObservableCreate.java:74)
at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:43)
at io.reactivex.Observable.subscribe(Observable.java:11194)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:463)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.lang.InterruptedException
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:373)
at java.lang.Thread.sleep(Thread.java:314)
at com.elyeproj.porterduff.AnimateDrawPorterDuffView$startAnimate.subscribe(AnimateDrawPorterDuffView.kt:45)
at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:40)
at io.reactivex.Observable.subscribe(Observable.java:11194)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:463)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
为什么 InterruptedException
没有被 RxJava 中的 onError
捕获?
正如@akarnokd 所指出的,在https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling 中,看起来 RxJava 在抛出之前已经被处理掉了,因此后来抛出的错误得到了解决。要解决这个问题只需要注册
RxJavaPlugins.setErrorHandler { e -> /*Do whatever we need with the error*/ }
下面我有一个简单的代码
compositeDisposable.add(Observable.create<Int> { Thread.sleep(1000) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({}, {Log.d("Track", it.localizedMessage)}, {}))
Handler().postDelayed({compositeDisposable.clear()}, 100)
故意使用Thread.sleep(1000)
,就是为了触发InterruptedException
。我故意延迟 100 毫秒,以确保链中的睡眠已经开始,并将其处理掉。
(注意,我知道使用 Thread.sleep
不是首选。我只是编写这段代码来测试和理解为什么 onError
在这种情况下没有被调用,以及如何防止无需在 RxJava 链中使用 try-catch 即可优雅地崩溃)
当时,当它被触发时,错误不是 onError
的原因(即没有达到 Log
。而是抛出以下错误并使应用程序崩溃。
io.reactivex.exceptions.UndeliverableException: java.lang.InterruptedException
at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:366)
at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.onError(ObservableCreate.java:74)
at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:43)
at io.reactivex.Observable.subscribe(Observable.java:11194)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:463)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.lang.InterruptedException
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:373)
at java.lang.Thread.sleep(Thread.java:314)
at com.elyeproj.porterduff.AnimateDrawPorterDuffView$startAnimate.subscribe(AnimateDrawPorterDuffView.kt:45)
at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:40)
at io.reactivex.Observable.subscribe(Observable.java:11194)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeTask.run(ObservableSubscribeOn.java:96)
at io.reactivex.Scheduler$DisposeTask.run(Scheduler.java:463)
at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
为什么 InterruptedException
没有被 RxJava 中的 onError
捕获?
正如@akarnokd 所指出的,在https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling 中,看起来 RxJava 在抛出之前已经被处理掉了,因此后来抛出的错误得到了解决。要解决这个问题只需要注册
RxJavaPlugins.setErrorHandler { e -> /*Do whatever we need with the error*/ }