RxJava 错误处理操作符(Error Handling Operators)
来源:互联网 发布:快阅读软件 编辑:程序博客网 时间:2024/05/18 00:20
RxJava系列教程:
1. RxJava使用介绍 【视频教程】
2. RxJava操作符
• Creating Observables(Observable的创建操作符) 【视频教程】
• Transforming Observables(Observable的转换操作符) 【视频教程】
• Filtering Observables(Observable的过滤操作符) 【视频教程】
• Combining Observables(Observable的组合操作符) 【视频教程】
• Error Handling Operators(Observable的错误处理操作符) 【视频教程】
• Observable Utility Operators(Observable的辅助性操作符) 【视频教程】
• Conditional and Boolean Operators(Observable的条件和布尔操作符) 【视频教程】
• Mathematical and Aggregate Operators(Observable数学运算及聚合操作符) 【视频教程】
• 其他如observable.toList()、observable.connect()、observable.publish()等等; 【视频教程】
3. RxJava Observer与Subcriber的关系 【视频教程】
4. RxJava线程控制(Scheduler) 【视频教程】
5. RxJava 并发之数据流发射太快如何办(背压(Backpressure)) 【视频教程】
一般来说,Observable不会抛异常。它会调用 onError 终止Observable序列,以此通知所有的观察者发生了一个不可恢复的错误。 但是,也存在一些异常。例如,如果 onError 调用失败了,Observable不会尝试再次调用 onError 去通知观察者,它会抛出 RuntimeException,OnErrorFailedException 或者 OnErrorNotImplementedException。
有时我们希望观察者或者操作符应该对异常发生时的 onError 通知做出合适的响应,而不是捕获(catch)异常。很多操作符可用于对Observable发射的onError通知做出响应或者从错误中恢复,例如,你可以:
- 吞掉这个错误,切换到一个备用的Observable继续发射数据
- 吞掉这个错误然后发射默认值
- 吞掉这个错误并立即尝试重启这个Observable
- 吞掉这个错误,在一些回退间隔后重启这个Observable
我们可以使用Error handling相关的操作符来集中统一地处理错误。RxJava中错误处理的操作符为 Catch和 Retry。
Catch
Catch操作符能够拦截原始Observable的onError通知,不让Observable因为产生错误而终止。相当于Java中try/catch操作,不能因为抛异常而导致程序崩溃。
RxJava将Catch实现为三个不同的操作符:
onErrorReturn:让Observable遇到错误时发射一个特殊的项并且正常终止。
onErrorResumeNext:让Observable在遇到错误时开始发射第二个Observable的数据序列。
onExceptionResumeNext:让Observable在遇到错误时继续发射后面的数据项。
onErrorReturn
onErrorReturn方法 返回一个镜像原有Observable行为的新Observable
会忽略前者的onError调用,不会将错误传递给观察者,而是发射一个特殊的项并调用观察者的onCompleted方法。
API
Javadoc: onErrorReturn(Func1))
示例代码
/* * onErrorReturn: * 返回一个原有Observable行为的新Observable镜像, * 后者会忽略前者的onError调用,不会将错误传递给观察者, * 作为替代,它会发发射一个特殊的项并调用观察者的onCompleted方法 */createObserver() //作为替代,它会发发射一个特殊的项并调用观察者的onCompleted方法。 .onErrorReturn(new Func1<Throwable, String>() { @Override public String call(Throwable throwable) { return "do something"; } }) .subscribe(new Subscriber<String>() { @Override public void onCompleted() { System.out.println("onCompleted"); } @Override public void onNext(String value) { System.out.println("onSuccess value = " + value); } @Override public void onError(Throwable error) { System.out.println("onError error = " + error); } });
这里创建Observable的方法(2个)如下:
private static Observable<String> createObserver() { return Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { for (int i = 1; i <= 6; i++) { if (i < 3) { subscriber.onNext(i+""); } else { //会忽略onError调用,不会将错误传递给观察者 subscriber.onError(new Throwable("Throw error")); } } } }); } private static Observable<String> createObserver2() { return Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { for (int i = 1; i <= 6; i++) { if (i < 3) { subscriber.onNext("onNext:" + i); } else { subscriber.onError(new Exception("the nubmer is greater than 3")); //下面写法也是可以的 /*try { throw new Exception("the nubmer is greater than 3"); } catch (Exception e) { subscriber.onError(e); }*/ } } } }); }
输出结果如下:
onSuccess value = 1onSuccess value = 2onSuccess value = do somethingonCompleted
在手动创建Observale时,当Observable发送了第二个数据后,Observable发送了onError通知,然后又发送了1个数据。而在onErrorReturn方法处理中,其参数函数中,创建并返回了一个特殊项( do something).
从Log打印可以看出,观察者并没有执行onError方法,意味着Observale并没有接收到onError通知,而是接收到了一个特殊项后,调用了onCompleted方法,结束了此次订阅。而这个特殊项,正是在onErrorReturn中参数函数中,创建的特殊项。
onErrorResumeNext
onErrorResumeNext方法与onErrorReturn()方法类似,都是拦截原Observable的onError通知,不同的是拦截后的处理方式,onErrorReturn创建并返回一个特殊项,而onErrorResumeNext创建并返回一个新的Observabl,观察者会订阅它,并接收其发射的数据。
API
Javadoc: onErrorResumeNext(Func1))
Javadoc: onErrorResumeNext(Observable))
示例代码
createObserver() .onErrorResumeNext(new Func1<Throwable, Observable<? extends String>>() { @Override public Observable<String> call(Throwable t) { return Observable.just("a","b","c"); } }) .subscribe(new Subscriber<String>() { @Override public void onCompleted() { System.out.println("onCompleted"); } @Override public void onNext(String value) { System.out.println("onSuccess value = " + value); } @Override public void onError(Throwable error) { System.out.println("onError error = " + error); } });
输出结果如下:
onSuccess value = 1onSuccess value = 2onSuccess value = aonSuccess value = bonSuccess value = conCompleted
在手动创建Observale时,当Observable发送了第二个数据后,Observable发送了onError通知,然后又发送了3个数据。在onErrorResumeNext方法中的参数函数中,创建了一个新的Observable。
从Log打印可以看出,观察者并没有执行onError方法,意味着Observale并没有接收到onError通知,而是接收到了新建的创建了一个新的Observable发射的出具。在新Observable发射完数据后,调用了onCompleted方法,结束了此次订阅。
onExceptionResumeNext
onExceptionResumeNext方法与onErrorResumeNext方法类似创建并返回一个拥有类似原Observable的新Observable,,也使用这个备用的Observable。不同的是,如果onError收到的Throwable不是一个Exception,它会将错误传递给观察者的onError方法,不会使用备用的Observable。
这里要普及一个概念,Java的异常分为错误(error)和异常(exception)两种,它们都是继承于Throwable类。
错误(error)一般是比较严重的系统问题,比如我们经常遇到的OutOfMemoryError、StackOverflowError等都是错误。错误一般继承于Error类,而Error类又继承于Throwable类,如果需要捕获错误,需要使用try..catch(Error e)或者try..catch(Throwable e)句式。使用try..catch(Exception e)句式无法捕获错误
异常(Exception)也是继承于Throwable类,一般是根据实际处理业务抛出的异常,分为运行时异常(RuntimeException)和普通异常。普通异常直接继承于Exception类,如果方法内部没有通过try..catch句式进行处理,必须通过throws关键字把异常抛出外部进行处理(即checked异常);而运行时异常继承于RuntimeException类,如果方法内部没有通过try..catch句式进行处理,不需要显式通过throws关键字抛出外部,如IndexOutOfBoundsException、NullPointerException、ClassCastException等都是运行时异常,当然RuntimeException也是继承于Exception类,因此是可以通过try..catch(Exception e)句式进行捕获处理的。
API
Javadoc: onExceptionResumeNext(Observable))
示例代码
/* * onExceptionResumeNext: * 和onErrorResumeNext类似,可以说是onErrorResumeNext的特例, * 区别是如果onError收到的Throwable不是一个Exception,它会将错误传递给观察者的onError方法,不会使用备用的Observable。 */createObserver() .onExceptionResumeNext(Observable.just("www.stay4it.com")) .subscribe(new Subscriber<String>() { @Override public void onCompleted() { System.out.println("onCompleted"); } @Override public void onNext(String value) { System.out.println("onSuccess value = " + value); } @Override public void onError(Throwable error) { System.out.println("onError error = " + error); } });
输出结果如下:
onSuccess value = 1onSuccess value = 2onError error = java.lang.Throwable: Throw error
从Log打印可以看出,没有使用备用的Observable,这是因为onError收到的Throwable不是一个Exception,所以将错误传递给观察者的onError方法。那么怎么才能使用备用的Observable呢?代码如下:
createObserver2()// 注意这里 .onExceptionResumeNext(Observable.just("www.stay4it.com")) .subscribe(new Subscriber<String>() { @Override public void onCompleted() { System.out.println("onCompleted"); } @Override public void onNext(String value) { System.out.println("onSuccess value = " + value); } @Override public void onError(Throwable error) { System.out.println("onError error = " + error); } });
输出结果如下:
onSuccess value = onNext:1onSuccess value = onNext:2onSuccess value = www.stay4it.comonCompleted
Retry
顾名思义,retry的意思就是试着重来,当原始Observable发射onError通知时,retry操作符不会让onError通知传递给观察者,它会重新订阅这个Observable一次或者多次(意味着重新从头发射数据),所以可能造成数据项重复发送的情况。
如果重新订阅了指定的次数还是发射了onError通知,将不再尝试重新订阅,它会把最新的一个onError通知传递给观察者。
RxJava中将Retry操作符的实现为retry和retryWhen两种。
retry操作符默认在trampoline调度器上执行。
Javadoc: retry():无论收到多少次onError通知,都会继续订阅并重发原始Observable,直到onCompleted。
Javadoc: retry(long):接受count参数的retry会最多重新订阅count次,如果次数超过了就不会尝试再次订阅,它会把最新的一个onError通知传递给他的观察者。
Javadoc: retry(Func2): 这个版本的retry接受一个谓词函数作为参数,这个函数的两个参数是:重试次数和导致发射onError通知的Throwable。这个函数返回一个布尔值,如果返回true,retry应该再次订阅和镜像原始的Observable,如果返回false,retry会将最新的一个onError通知传递给它的观察者。
API
Javadoc: retry()
Javadoc: retry(long)
Javadoc: retry(Func2)
示例代码
/** * retry() * 无限次尝试重新订阅 */createObserver() .retry() .subscribe(new Subscriber<String>() { @Override public void onCompleted() { System.out.println("onCompleted"); } @Override public void onNext(String value) { System.out.println("onSuccess value = " + value); } @Override public void onError(Throwable error) { System.out.println("onError error = " + error); } });/** * retry(count) * 最多2次尝试重新订阅 */createObserver() .retry(2) .subscribe(new Subscriber<String>() { @Override public void onCompleted() { System.out.println("onCompleted"); } @Override public void onNext(String value) { System.out.println("onSuccess value = " + value); } @Override public void onError(Throwable error) { System.out.println("onError error = " + error); } });/** * retry(Func2) */createObserver() .retry(new Func2<Integer, Throwable, Boolean>() { @Override public Boolean call(Integer t1, Throwable throwable) { System.out.println("发生错误了:"+throwable.getMessage()+",第"+t1+"次重新订阅"); if(t1>2){ return false;//不再重新订阅 } //此处也可以通过判断throwable来控制不同的错误不同处理 return true; } }) .subscribe(new Subscriber<String>() { @Override public void onCompleted() { System.out.println("onCompleted"); } @Override public void onNext(String value) { System.out.println("onSuccess value = " + value); } @Override public void onError(Throwable error) { System.out.println("onError error = " + error); } });
输出结果如下:
onSuccess value = 1onSuccess value = 2onSuccess value = 1onSuccess value = 2…无限次onSuccess value = 1onSuccess value = 2onSuccess value = 1onSuccess value = 2onSuccess value = 1onSuccess value = 2onError error = java.lang.Throwable: Throw erroronSuccess value = 1onSuccess value = 2发生错误了:Throw error,第1次重新订阅onSuccess value = 1onSuccess value = 2发生错误了:Throw error,第2次重新订阅onSuccess value = 1onSuccess value = 2发生错误了:Throw error,第3次重新订阅onError error = java.lang.Throwable: Throw error
retryWhen
retryWhen和retry类似,区别是,retryWhen将onError中的Throwable传递给一个函数,这个函数产生另一个Observable,retryWhen观察它的结果再决定是不是要重新订阅原始的Observable。如果这个Observable发射了一项数据,它就重新订阅,如果这个Observable发射的是onError通知,它就将这个通知传递给观察者然后终止。
retryWhen()默认在trampoline调度器上执行,可以通过参数指定其它的调度器。
API
Javadoc: retryWhen(Func1)
Javadoc: retryWhen(Func1,Scheduler)
示例代码
int retryCount = 0;final int maxRetries = 3; Observable.create(new Observable.OnSubscribe<Integer>() { @Override public void call(Subscriber<? super Integer> subscriber) { subscriber.onError(new RuntimeException("always fails")); } }) .subscribeOn(Schedulers.immediate()) .retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() { @Override public Observable<?> call(Observable<? extends Throwable> observable) { return observable.flatMap(new Func1<Throwable, Observable<?>>() { @Override public Observable<?> call(Throwable throwable) { if (++retryCount <= maxRetries) { // When this Observable calls onNext, the original Observable will be retried (i.e. re-subscribed). System.out.println("get error, it will try after " + 1000 + " millisecond, retry count " + retryCount); return Observable.timer(1000, TimeUnit.MILLISECONDS); } return Observable.error(throwable); } }); } }) .subscribe(new Subscriber<Integer>() { @Override public void onCompleted() { System.out.println("onCompleted"); } @Override public void onNext(Integer value) { System.out.println("onSuccess value = " + value); } @Override public void onError(Throwable error) { System.out.println("onError error = " + error); } });
输出结果如下:
get error, it will try after 1000 millisecond, retry count 1get error, it will try after 1000 millisecond, retry count 2get error, it will try after 1000 millisecond, retry count 3onError error = java.lang.RuntimeException: always fails
- RxJava 错误处理操作符(Error Handling Operators)
- RxJava 错误处理操作符(Error Handling Operators)
- RxJava 学习笔记(九) --- Error Handling 错误处理操作
- RxJava操作符(五)Error Handling
- RxJava操作符(五)Error Handling
- RxJava操作符(五)Error Handling
- RxJava操作符(五)Error Handling
- RxJava操作符(五)Error Handling
- 错误处理(Error Handling)
- Error Handling 错误处理
- 错误处理(Error Handling)
- Swift错误处理(Error Handling)
- RxJava----操作符:错误处理
- 错误处理(Error-Handling):为何、何时、如何
- 错误处理(Error-Handling):为何、何时、如何
- Swift 错误处理(Error Handling)
- 7.5 Error Handling 错误处理 - Catch/Retry
- RxJava操作符(06-错误处理)
- android图片叠加代码
- java 实现定时器修改
- js队列方法push()、shift()与pop()、unshift()的理解
- Eigen:矩阵计算简单用法(一)
- 基于maven搭建ssm开发框架(1) Service层整合
- RxJava 错误处理操作符(Error Handling Operators)
- hibernate自带的常用方法
- iOS 电话监听,后台工作问题
- 关于PLSQL本地连接总是报错的问题
- 基于Intel®IPP的MPEG-2编码技术研究及实现
- JAVA-泛型-学习笔记
- VS2015使用小技巧 利用断点调试查看父类装的是哪个子类对象
- Mac终端设置颜色、安装ctags及vim配置
- dump文件调试技巧(产生Dump文件)