一次RxJava2导致的线上崩溃问题:The exception was not handled due to missing onError handler in the subscribe()

周末正在休(玩)息(LOL),突然产品告诉我线上崩溃率很高,还记得周五测试很忙,没怎么测产品就急着上线了。

吓得我感觉看了下友盟数据,发现错误频次最高的是一个网络请求无法解析域名的异常:

第一反应:国外用户无法解析我们配置后台数据的域名,但是理论上来说也应该是网络错误,而不是闪退呀。

第二反应:看到错误的抛出地址是

io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.void accept(java.lang.Throwable)(Functions.java:704)

是RxJava2里面,仔细看了一下我写的调用代码:

RetrofitManager.service.getConfig(getCommonHead(),map)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .`as`(autoDisposable(AndroidLifecycleScopeProvider.from(this)))
                    .subscribe {
                        ...
                    }

就是个简单的网络请求配合RxJava2和AutoDispose,看上去莫得问题,因为错误里面有提到“subscribe()”这个方法,查看源码:

注释中明确提到如果被观察者发射了一个error事件,会被封装成一个OnErrorNotImplementedException异常,然后发送给RxJavaPlugins的onError全局处理。

然后我先看了一下subscribe方法的error回调Functions.ON_ERROR_MISSING:

//1
public static final Consumer<Throwable> ON_ERROR_MISSING = new OnErrorMissingConsumer();
//2
static final class OnErrorMissingConsumer implements Consumer<Throwable> {
        @Override
        public void accept(Throwable error) {
            RxJavaPlugins.onError(new OnErrorNotImplementedException(error));
        }
    }

//3
public OnErrorNotImplementedException(@NonNull Throwable e) {
        this("The exception was not handled due to missing onError handler in the subscribe() method call. Further reading: https://github.com/ReactiveX/RxJava/wiki/Error-Handling | " + e, e);
    }

可以看到里面的错误信息就是我们上面遇到的那个错误,只是这里交给了RxJavaPlugins的onError,而没有直接抛出来。

public static void onError(@NonNull Throwable error) {
        Consumer<? super Throwable> f = errorHandler;

        if (error == null) {
            error = new NullPointerException("onError called with null. Null values are generally not allowed in 2.x operators and sources.");
        } else {
            if (!isBug(error)) {
                error = new UndeliverableException(error);
            }
        }

        if (f != null) {
            try {
                f.accept(error);
                return;
            } catch (Throwable e) {
                // Exceptions.throwIfFatal(e); TODO decide
                e.printStackTrace(); // NOPMD
                uncaught(e);
            }
        }

        error.printStackTrace(); // NOPMD
        uncaught(error);
    }

可以看到这个方法里面就是检查了是否为空,然后如果errorHandler不为空,就交给f处理,否则直接通过uncaught()方法抛出异常。

所以问题就在于errorHandler这里,注释里面有相关说明:

大概意思就是说,这个方法是用来接收一些本应该回调到onError但是因为一些原因无法回调的事件,默认会打印异常信息然后抛出异常停止程序,为了避免这种情况,建议我们通过setErrorHandler方法设置一个全局异常处理

 

分析完毕:

     原因就是因为我没实现onError然后有没有全局异常处理器。所以解决方法有两个,1.在调用处加上onError的实现,2.通过RxJavaPlugins.setErrorHandler设置一个全局的回调。第一种方法适合你的异常需要单独处理的情况,第二种适合你的异常处理方式一致或者说不处理的情况。我选择了第二种,一方面是因为我的情况不需要处理,另一方面也是为了避免之后再次因为这个问题闪退。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
Welcome! You must be here because you want to write programs for your Mac. Well, you’ve definitely come to the right place. (Here for Pilates? Third door down, on the right.) By the time you finish this book, you’ll know everything you need to know to create fast, efficient, good-looking Mac OS X applications. The key to creating a modern Mac application is Cocoa. According to Apple, Cocoa is a set of object-oriented frameworks that provide a runtime environment for Mac OS X applications. As you make your way through this book, you’ll learn all about the Cocoa frameworks and runtime environment. For the moment, think of Cocoa as a programmer’s assistant that takes care of much of the housekeeping that goes along with Mac development. Almost every common task performed by a Mac application, from drawing a window to blinking the cursor in a text field, is handled for you when you write programs using Cocoa, freeing you up to concentrate on the code that makes your application unique. Cocoa provides a class for just about every one of your development needs. There are Cocoa classes for each piece of the Mac OS X user interface, from windows to menus, scrollbars to buttons, images to icons. If you can think of a user interface element you’d like to add to your own application, chances are very good that element is already implemented as a Cocoa class. Another benefit of using Cocoa is that it is tightly integrated with Mac OS X. Build your application using Cocoa, and your application will play well with others and will interface seamlessly with Mac OS X elements like the Finder and the Dock. Cocoa has been around in one form or another since 1986. The technologies that we call Cocoa evolved from the NeXTStep AppKit, the application building tools developed for the NeXT platform. When Apple bought NeXT in 1996, they began building a new version of the Mac OS, what we now know as OS X, basing much of the new operating system on technologies acquired from NeXT.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值