解决使用RxJava时出现的io.reactivex.exceptions.UndeliverableException异常问题

本文深入探讨了在使用RxJava时遇到的UndeliverableException异常及其原因,提供了在Application中设置RxJava错误处理器的方法,以捕捉并处理多次发生的错误。

使用RxJava时,有时会出现:io.reactivex.exceptions.UndeliverableException异常。
出现这个异常的原因大概是:调用了多次onError。正常来说第一次onError会走正常Observer处理,其他的会走ErrorHandler。可以通过如下方法捕捉多次的error,此方法只需要在Application中执行一次即可。

private void setRxJavaErrorHandler() {
    RxJavaPlugins.setErrorHandler(new Consumer<Throwable>() {
        @Override
        public void accept(Throwable e) {
            if (e instanceof UndeliverableException) {
                e = e.getCause();
                Log.d(TAG, "UndeliverableException=" + e);
                return;
            } else if ((e instanceof IOException)) {
                // fine, irrelevant network problem or API that throws on cancellation
                return;
            } else if (e instanceof InterruptedException) {
                // fine, some blocking code was interrupted by a dispose call
                return;
            } else if ((e instanceof NullPointerException) || (e instanceof IllegalArgumentException)) {
                // that's likely a bug in the application
                Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                return;
            } else if (e instanceof IllegalStateException) {
                // that's a bug in RxJava or in a custom operator
                Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                return;
            }
            Log.d(TAG, "unknown exception=" + e);
        }
    });
}

 

[399922.833s] GC(172630) Full GC (Collect on allocation) 1098.00M->975.25M 30876.419ms io.reactivex.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&#39;s-different-in-2.0#error-handling | java.util.concurrent.TimeoutException: The source did not signal an event for 30000 milliseconds and has been terminated. at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367) at io.reactivex.internal.operators.single.SingleZipArray$ZipCoordinator.innerError(SingleZipArray.java:139) at io.reactivex.internal.operators.single.SingleZipArray$ZipSingleObserver.onError(SingleZipArray.java:175) at io.reactivex.internal.operators.single.SingleTimeout$TimeoutMainObserver.run(SingleTimeout.java:123) at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:38) at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:26) at java.base@21.0.5/java.util.concurrent.FutureTask.run(FutureTask.java:317) at java.base@21.0.5/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) at java.base@21.0.5/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base@21.0.5/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base@21.0.5/java.lang.Thread.runWith(Thread.java:1596) at java.base@21.0.5/java.lang.Thread.run(Thread.java:1583) at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:902) at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:878) Caused by: java.util.concurrent.TimeoutException: The source did not signal an event for 30000 milliseconds and has been terminated. ... 11 more Exception in thread "RxComputationThreadPool-3" io.reactivex.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&#39;s-different-in-2.0#error-handling | java.util.concurrent.TimeoutException: The source did not signal an event for 30000 milliseconds and has been terminated. at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367) at io.reactivex.internal.operators.single.SingleZipArray$ZipCoordinator.innerError(SingleZipArray.java:139) at io.reactivex.internal.operators.single.SingleZipArray$ZipSingleObserver.onError(SingleZipArray.java:175) at io.reactivex.internal.operators.single.SingleTimeout$TimeoutMainObserver.run(SingleTimeout.java:123) at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:38) at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:26) at java.base@21.0.5/java.util.concurrent.FutureTask.run(FutureTask.java:317) at java.base@21.0.5/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) at java.base@21.0.5/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base@21.0.5/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base@21.0.5/java.lang.Thread.runWith(Thread.java:1596) at java.base@21.0.5/java.lang.Thread.run(Thread.java:1583) at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:902) at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:878) Caused by: java.util.concurrent.TimeoutException: The source did not signal an event for 30000 milliseconds and has been terminated. ... 11 more io.reactivex.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&#39;s-different-in-2.0#error-handling | java.util.concurrent.TimeoutException: The source did not signal an event for 30000 milliseconds and has been terminated. at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367) at io.reactivex.internal.operators.single.SingleZipArray$ZipCoordinator.innerError(SingleZipArray.java:139) at io.reactivex.internal.operators.single.SingleZipArray$ZipSingleObserver.onError(SingleZipArray.java:175) at io.reactivex.internal.operators.single.SingleTimeout$TimeoutMainObserver.run(SingleTimeout.java:123) at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:38) at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:26) at java.base@21.0.5/java.util.concurrent.FutureTask.run(FutureTask.java:317) at java.base@21.0.5/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) at java.base@21.0.5/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base@21.0.5/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base@21.0.5/java.lang.Thread.runWith(Thread.java:1596) at java.base@21.0.5/java.lang.Thread.run(Thread.java:1583) at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:902) at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:878) Caused by: java.util.concurrent.TimeoutException: The source did not signal an event for 30000 milliseconds and has been terminated. ... 11 more Exception in thread "RxComputationThreadPool-2" io.reactivex.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&#39;s-different-in-2.0#error-handling | java.util.concurrent.TimeoutException: The source did not signal an event for 30000 milliseconds and has been terminated. at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367) at io.reactivex.internal.operators.single.SingleZipArray$ZipCoordinator.innerError(SingleZipArray.java:139) at io.reactivex.internal.operators.single.SingleZipArray$ZipSingleObserver.onError(SingleZipArray.java:175) at io.reactivex.internal.operators.single.SingleTimeout$TimeoutMainObserver.run(SingleTimeout.java:123) at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:38) at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:26) at java.base@21.0.5/java.util.concurrent.FutureTask.run(FutureTask.java:317) at java.base@21.0.5/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) at java.base@21.0.5/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) at java.base@21.0.5/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) at java.base@21.0.5/java.lang.Thread.runWith(Thread.java:1596) at java.base@21.0.5/java.lang.Thread.run(Thread.java:1583) at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:902) at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:878) Caused by: java.util.concurrent.TimeoutException: The source did not signal an event for 30000 milliseconds and has been terminated. ... 11 more [399925.643s] GC(172631) Collect on allocation
11-18
25.11.11 10:19:18.703,HALO-RxJavaPlugins,[1762827558702], [main] : io.reactivex.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&#39;s-different-in-2.0#error-handling | java.lang.RuntimeException: Cannot create an instance of class com.tplink.libtpnetwork.MeshNetwork.repository.MeshNetworkRepository at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:21) at io.reactivex.internal.operators.observable.ObservableDoFinally$DoFinallyObserver.runFinally(ObservableDoFinally.java:19) at io.reactivex.internal.operators.observable.ObservableDoFinally$DoFinallyObserver.onError(ObservableDoFinally.java:6) at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.checkTerminated(ObservableObserveOn.java:48) at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:13) at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:9) at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:3) at android.os.Handler.handleCallback(Handler.java:973) at android.os.Handler.dispatchMessage(Handler.java:100) at android.os.Looper.loopOnce(Looper.java:282) at android.os.Looper.loop(Looper.java:387) at android.app.ActivityThread.main(ActivityThread.java:9500) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:600) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1005) Caused by: java.lang.RuntimeException: Cannot create an instance of class com.tplink.libtpnetwork.MeshNetwork.repository.MeshNetworkRepository at com.tplink.libtpnetwork.MeshNetwork.repository.base.MeshRepositoryProvider$MercusysRepositoryFactory.create(MeshRepositoryProvider.java:77) at com.tplink.libtpnetwork.MeshNetwork.repository.base.MeshRepositoryProvider.get(MeshRepositoryProvider.java:16) at com.tplink.libtpnetwork.MeshNetwork.repository.base.MeshRepositoryProvider.get(MeshRepositoryProvider.java:29) at com.tplink.libtpnetwork.MeshNetwork.repository.base.MeshRepositoryProviders.create(MeshRepositoryProviders.java:5) at com.tplink.mercusys.component.core.lifecycle.AppAutoConnectObserver.<init>(AppAutoConnectObserver.java:49) at com.tplink.mercusys.base.lifecycle.ApplicationStateReceiverDelegate.registerAutoConnectObserver(ApplicationStateReceiverDelegate.java:24) at com.tplink.mercusys.component.core.lifecycle.AppAutoConnectObserver.registerObserver(AppAutoConnectObserver.java:40) at com.tplink.mercusys.component.core.lifecycle.AppAutoConnectObserver.lambda$reconnectNetwork$6(AppAutoConnectObserver.java:5) at com.tplink.mercusys.component.core.lifecycle.AppAutoConnectObserver.$r8$lambda$0wm0luLOiA5Kpxus6DcbXQTe8mk(AppAutoConnectObserver.java:1) at com.tplink.mercusys.component.core.lifecycle.AppAutoConnectObserver$$ExternalSyntheticLambda10.run(R8$$SyntheticClass:3) at io.reactivex.internal.operators.observable.ObservableDoFinally$DoFinallyObserver.runFinally(ObservableDoFinally.java:11) ... 13 more Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Constructor.newInstance0(Native Method) at java.lang.reflect.Constructor.newInstance(Constructor.java:343) at com.tplink.libtpnetwork.MeshNetwork.repository.base.MeshRepositoryProvider$MercusysRepositoryFactory.create(MeshRepositoryProvider.java:21) ... 23 more Caused by: java.lang.NullPointerException: Attempt to invoke virtual method &#39;kg.b jg0.a.a()&#39; on a null object reference at com.tplink.libtpnetwork.MeshNetwork.repository.MeshNetworkRepository.<init>(MeshNetworkRepository.java:51) ... 26 more
11-18
`io.reactivex.exceptions.CompositeException: 2 exceptions occurred` 表示在 RxJava 执行过程中同发生了两个异常,被合并成了一个 `CompositeException`。以下是一些可能的解决方法: ### 1. 捕获并处理异常RxJava 链中使用 `onErrorResumeNext` 或 `onErrorReturn` 操作符来捕获并处理异常。示例代码如下: ```java import io.reactivex.Observable; import io.reactivex.functions.Function; public class RxJavaErrorHandling { public static void main(String[] args) { Observable.just(1, 2, 3) .map(new Function<Integer, Integer>() { @Override public Integer apply(Integer integer) throws Exception { if (integer == 2) { throw new RuntimeException("Error for value 2"); } return integer; } }) .onErrorResumeNext(Observable.empty()) .subscribe(System.out::println); } } ``` 在上述代码中,`onErrorResumeNext` 操作符在遇到异常返回一个空的 `Observable`,避免异常继续传播。 ### 2. 检查取消订阅情况 确保在取消订阅后,请求线程不会继续执行并抛出异常。可以使用 `takeUntil` 操作符来控制订阅的生命周期。示例代码如下: ```java import io.reactivex.Observable; import io.reactivex.subjects.PublishSubject; public class RxJavaCancelSubscription { public static void main(String[] args) { PublishSubject<Boolean> stopSignal = PublishSubject.create(); Observable.just(1, 2, 3) .takeUntil(stopSignal) .subscribe(System.out::println); // 发送取消订阅信号 stopSignal.onNext(true); } } ``` 在上述代码中,`takeUntil` 操作符在接收到 `stopSignal` 停止订阅,避免后续异常的产生。 ### 3. 日志记录和调试 在 `subscribe` 方法中添加 `onError` 回调,记录异常信息,以便更好地定位问题。示例代码如下: ```java import io.reactivex.Observable; public class RxJavaLogging { public static void main(String[] args) { Observable.just(1, 2, 3) .map(integer -> { if (integer == 2) { throw new RuntimeException("Error for value 2"); } return integer; }) .subscribe( System.out::println, throwable -> System.err.println("Error: " + throwable.getMessage()) ); } } ``` 在上述代码中,`onError` 回调记录了异常信息,方便调试。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值