日常开发中遇到的 RxJava2.0 问题,在这里进行一个简单的记录,也希望可以帮助到更多被这些问题困扰的小伙伴们 ,持续更新…
io.reactivex.exceptions.UndeliverableException RxJava2 取消订阅后,抛出的异常无法捕获,导致程序崩溃: 详细异常打印日志:(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.)
UndeliverableException 从字面意思看,意思是不可送达的异常。 通过源码跟踪,发现抛出io.reactivex.exceptions.UndeliverableException 唯一地方是 RxJavaPlugins 类。
RxJava2 当取消订阅后(dispose()),RxJava 抛出的异常后续无法接收(此时后台线程仍在跑,可能会抛出IO等异常),全部由 RxJavaPlugin 接收,需要提前设置 ErrorHandler.
RxJava2的一个重要的设计理念是:不吃掉任何一个异常。产生的问题是,当RxJava2“downStream”取消订阅后,“upStream”仍有可能抛出异常,这时由于已经取消订阅,“downStream”无法处理异常,此时的异常无人处理,便会导致程序崩溃。
个人出问题的代码,也是常规写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Observable.create((ObservableOnSubscribe<HouseVOListSchema>) emitter -> { if (isViewAttached()) { try { ResultBean result = apiInstance.requestData(token); if (result == null) { emitter.onError(new NullPointerException()); } else { emitter.onNext(result); emitter.onComplete(); } } catch (ApiException e) { Trace.e("Rxjava 接口调用异常", "getSearchPageIndex123 e.getMessage() "+e.getMessage() + " e.getCode() "+e.getCode()+" e.getResponseBody() " +e.getResponseBody()); emitter.onError(e); } } }).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) // Memory leak .as(mMvpView.bindAutoDispose()) .subscribe(result -> { mMvpView.dismissLoading(); if (isViewAttached()) { if (AppConstant.RESPONSE_RESULE_CODE == result.getCode()) { mMvpView.onSuccess(result.getResult()); } else { mMvpView.onError(result.getMessage()); } } }, throwable -> mMvpView.onThrowable(throwable) );
就这种常规操作的代码,出问题了。
解决方案:在 Application 初始化时候设置 RxJavaPlugin 的 ErrorHandler
1 2 3 4 5 6 private void setRxJavaErrorHandler() { RxJavaPlugins.setErrorHandler(throwable -> { throwable.printStackTrace(); Trace.e("MyApplication", "MyApplication setRxJavaErrorHandler " + throwable.getMessage()); }); }