RxJava2可观测take抛出不可交付异常

RxJava2可观测take抛出不可交付异常,java,observable,rx-java2,take,Java,Observable,Rx Java2,Take,据我所知,RxJava2values.take(1)创建了另一个只包含原始可观察对象中一个元素的可观察对象。当异常被take(1)的效果过滤掉时,它不能抛出一个异常 与下面的代码片段一样 Observable<Integer> values = Observable.create(o -> { o.onNext(1); o.onError(new Exception("Oops")); }); values.take(1

据我所知,RxJava2
values.take(1)
创建了另一个只包含原始可观察对象中一个元素的可观察对象。当异常被
take(1)
的效果过滤掉时,它不能抛出一个异常

与下面的代码片段一样

    Observable<Integer> values = Observable.create(o -> {
        o.onNext(1);
        o.onError(new Exception("Oops"));
    });

    values.take(1)
            .subscribe(
                    System.out::println,
                    e -> System.out.println("Error: " + e.getMessage()),
                    () -> System.out.println("Completed")
            );
我的问题是:
  • 我的理解正确吗
  • 导致异常的真正原因是什么
  • 如何从消费者的角度解决这个问题
  • 是的,但是因为可观察的“结束”并不意味着在
    create(…)
    中运行的代码被停止。为了在这种情况下完全安全,您需要使用
    o.isDisposed()
    来查看可观察对象是否已在下游结束
  • 这个例外是因为rxjava2的策略是永远不允许
    onError
    调用丢失。如果可观测对象已经终止,则它要么向下传递,要么作为全局
    不可传递异常抛出。由可观察对象的创建者“正确”处理可观察对象已结束且发生异常的情况
  • 问题是生产者(
    可观察的
    )和消费者(
    订户
    )在流结束时意见不一致。在这种情况下,由于生产者比消费者长寿,因此问题只能在生产者中解决

  • @Kiskae在之前的评论中正确地回答了出现这种异常的原因

    此处链接到有关此主题的官方文档:

    有时您无法更改此行为,因此有一种方法可以处理此
    无法交付的异常。以下是如何避免崩溃和不当行为的代码片段:

    RxJavaPlugins.setErrorHandler(e -> {
        if (e instanceof UndeliverableException) {
            e = e.getCause();
        }
        if ((e instanceof IOException) || (e instanceof SocketException)) {
            // fine, irrelevant network problem or API that throws on cancellation
            return;
        }
        if (e instanceof InterruptedException) {
            // fine, some blocking code was interrupted by a dispose call
            return;
        }
        if ((e instanceof NullPointerException) || (e instanceof IllegalArgumentException)) {
            // that's likely a bug in the application
            Thread.currentThread().getUncaughtExceptionHandler()
                .handleException(Thread.currentThread(), e);
            return;
        }
        if (e instanceof IllegalStateException) {
            // that's a bug in RxJava or in a custom operator
            Thread.currentThread().getUncaughtExceptionHandler()
                .handleException(Thread.currentThread(), e);
            return;
        }
        Log.warning("Undeliverable exception received, not sure what to do", e);
    });
    
    此代码取自上面的链接


    重要提示。这种方法将全局错误处理程序设置为RxJava,因此如果您能够消除这些异常,它将是更好的选择。

    在使用observable.create()时,只需使用tryOnError()。onError()不能保证错误会得到处理。科特林有很多种类型

    我在MainActivity onCreate方法中调用它

    private fun initRxErrorHandler(){
        RxJavaPlugins.setErrorHandler { throwable ->
            if (throwable is UndeliverableException) {
                throwable.cause?.let {
                    Thread.currentThread().uncaughtExceptionHandler?.uncaughtException(Thread.currentThread(), it)
                    return@setErrorHandler
                }
            }
            if (throwable is IOException || throwable is SocketException) {
                // fine, irrelevant network problem or API that throws on cancellation
                return@setErrorHandler
            }
            if (throwable is InterruptedException) {
                // fine, some blocking code was interrupted by a dispose call
                return@setErrorHandler
            }
            if (throwable is NullPointerException || throwable is IllegalArgumentException) {
                // that's likely a bug in the application
                Thread.currentThread().uncaughtExceptionHandler?.uncaughtException(Thread.currentThread(), throwable)
                return@setErrorHandler
            }
            if (throwable is IllegalStateException) {
                // that's a bug in RxJava or in a custom operator
                Thread.currentThread().uncaughtExceptionHandler?.uncaughtException(Thread.currentThread(), throwable)
                return@setErrorHandler
            }
            Log.w("Undeliverable exception", throwable)
        }
    }
    

    如果(!o.isDisposed()){o.onError(新异常(“Oops”));}
    是正确的处理方法吗?如果在不再观察到可观察对象的情况下该异常丢失是可以接受的,那么是。如果异常真的发生了,那么应该无条件地调用它。不,这需要在生产者中修复,因为使用者已声明自己已终止。如果(!o.isDisposed()){o.onError(new exception(“Oops”);}由于竞争条件的原因不是正确的处理方法(o可以在if条件和onError调用之间进行处理,这不是理论上的,它发生在生产系统中)。另请参阅此讨论:@AbdElraoufSabri一旦引入tryOnError,我就扔掉了该代码。可以在一些旧的提交中找到它,但现在出现tryOnError有什么意义?请参阅FlowableEmitter.tryOnError和2.1.1以来的类似方法。我无法摆脱这些异常,我需要从该RX获得一些数据,但当此错误发生时我无法从Json获取数据。我现在该怎么办(当我在
    中发出一些可观察的网络请求时。创建
    我的
    订户
    在网络呼叫开始时未被释放,并且在我收到呼叫响应时已被释放。是否有办法在
    RxJavaPlugins.setErrorHandler
    中不获取
    中断异常
    private fun initRxErrorHandler(){
        RxJavaPlugins.setErrorHandler { throwable ->
            if (throwable is UndeliverableException) {
                throwable.cause?.let {
                    Thread.currentThread().uncaughtExceptionHandler?.uncaughtException(Thread.currentThread(), it)
                    return@setErrorHandler
                }
            }
            if (throwable is IOException || throwable is SocketException) {
                // fine, irrelevant network problem or API that throws on cancellation
                return@setErrorHandler
            }
            if (throwable is InterruptedException) {
                // fine, some blocking code was interrupted by a dispose call
                return@setErrorHandler
            }
            if (throwable is NullPointerException || throwable is IllegalArgumentException) {
                // that's likely a bug in the application
                Thread.currentThread().uncaughtExceptionHandler?.uncaughtException(Thread.currentThread(), throwable)
                return@setErrorHandler
            }
            if (throwable is IllegalStateException) {
                // that's a bug in RxJava or in a custom operator
                Thread.currentThread().uncaughtExceptionHandler?.uncaughtException(Thread.currentThread(), throwable)
                return@setErrorHandler
            }
            Log.w("Undeliverable exception", throwable)
        }
    }