在研究生导师的公司里实习,公司说:你先学MVPArms吧,于是我就开启了Android开发的新视界。一周了过去了,CSDN、简书、github天天看,Retrofit、Rxjava、Dagger2、RxCache、Butterknife基本上都会用了,再加上之前学的MVP、OkHttp、Glide,感觉学习MVPArms指日可待。emm,小菜鸟要成长为大菜鸟了。。。
怎么说呢,虽然这些库都会用那么一点点吧,但是不懂源码就不知道这些库是怎么工作的,心里就很不舒服。源码还是要啃,但就是啃不进去呀。不过今天,我终于发现了一个源码还算简单的库——RxErrorHandler,所以我决定一定无论如何也要啃下去一个。ps:你问什么这个库简单?大概是因为它代码量没有劝退我吧。
为对MVPArms作者JessYan表示敬意,在此安装传送门:
- GitHub: https://github.com/JessYanCoding
- RxErrorHandler源码地址:https://github.com/JessYanCoding/RxErrorHandler
事先声明,水平有限,不当之处,敬请指出!
先从简单的重试机制看吧:
Rxjava的retryWhen操作符接受一个Function<Observable<Throwable>, ObservableSource<?>>对象,该对象用来实现你自己的重试逻辑,输入的是一个Observable<Throwable>,输出的是一个Observable<?>。被返回的Observable<?>所要发送的事件决定了重订阅是否会发生。如果发送的是onCompleted或者onError事件,将不会触发重订阅。相对的,如果它发送onNext事件,则触发重订阅(不管onNext实际上是什么事件)。
所以,泛型<?>并不重要,发送什么事件才重要。
RxErrorHandler中的RetryWithDelay类实现了Function接口其中包含三个成员变量 :
private final int maxRetries;
private final int retryDelaySecond;
private int retryCount;
分别记录最大重试数,重试延时,和已经重试次数。RetryWithDelay实现接口的apply()方法,每重试一次,retryCount++,如果retryCount < maxRetries ,就调用
Observable.timer(retryDelaySecond,TimeUnit.SECONDS)
在retryDelaySecond秒后发射一个事件(相当于调用了onNext()方法),该事件将导致调用retryWhen的Onservable触发重试。
如果retryCount >= maxRetries,就调用
Observable.error(throwable)
直接发射一个onError事件,该事件将导致调用retryWhen的Onservable放弃重试,将error事件下传。
服用方法:
Observable
.error(new Exception("Error"))
.retryWhen(new RetryWithDelay(3, 2))//重试3次,每次延时2秒
.subscribe();
然后来看看复杂点的错误处理
使用错误处理,就要构造出RxErrorHandler对象。我们可以通过Builder模式构造RxErrorHandler对象,传入参数Context和ResponseErrorListener。Context对象不用说了,上下文,很多地方要用,ResponseErrorListener是作者自定义的接口。
public interface ResponseErrorListener {
void handleResponseError(Context context, Throwable t);
}
接口只有一个方法handleResponseError(Context context, Throwable t),你要实现这个方法进行错误处理。
然而事实上,RxErrorHandler并不干活,在RxErrorHandler对象中只封装了 ErrorHandlerFactory对象mHandlerFactory,传入的参数Context对象和ResponseErrorListener对象都被封装进了mHandlerFactory里。mHandlerFactory中也只有一个方法handleError(Throwable throwable) 。
public void handleError(Throwable throwable) {
mResponseErrorListener.handleResponseError(mContext, throwable);
}
也就是用你传入的ResponseErrorListener对象进行回调。
之后就是和Rxjava相关了,敲黑板!别睡了!!
作者创建了类ErrorHandleSubscriber,类的声明如下:
public abstract class ErrorHandleSubscriber<T> implements Observer<T>
这是一个实现了Observer<T>的抽象类,但是里面并没有抽象方法哦。声明为抽象类,是为了在类里写一个构造方法:
public ErrorHandleSubscriber(RxErrorHandler rxErrorHandler) {
this.mHandlerFactory = rxErrorHandler.getHandlerFactory();
}
保证库的使用者在创建子类时,必须传入RxErrorHandler对象,毕竟人家还要靠RxErrorHandler获取mHandlerFactory干活呀,需要敲黑板的是:RxErrorHandler对象中的mHandlerFactory封装了上下文和ResponseErrorListener。
作者实现了Observer<T> 接口中的所有方法,基本上都是些空方法。为什么呢?估计是为了让你继承ErrorHandleSubscriber时少写一点代码吧。这些方法中只有onError方法是有代码的(ps:毕竟人家做的就是错误处理啊),不过别担心,代码也不多。
public void onError(@NonNull Throwable t) {
mHandlerFactory.handleError(t);
}
没骗你吧!!
前文说了,handleError(t) 中调用你传入的mResponseErrorListener回调处理错误,创建RxErrorHandler对象时传入的Context对象和ResponseErrorListener终于用上了。
服用方法:
Observable
.error(new Exception("Error"))
.subscribe(new ErrorHandleSubscriber<Object>(rxErrorHandler) {
@Override
public void onNext(Object o) {
}
});
另外还有个ErrorHandleSubscriberOfFlowable和RetryWithDelayOfFlowable,和上面讲的两个差不多,就不说了。
Q&A
为什么要这么做这么麻烦的事呢?
因为要进行统一的错误处理,只要发生错误,创建rxErrorHandler时传递的参数Context对象和ResponseErrorListener对象就能做一些所有错误的通用操作。
为啥要多一个RxErrorHandler呢?感觉就封装了个mHandlerFactory,没啥用啊?
emm...不知道!