java rx.observable_Rxjava2 Observable的错误处理操作详解及实例

简要:

需求了解:

Rxjava 中当数据处理派发中发生了异常 ,观察者会接受到一个 Error 的通知,那如果不想发射这个异常的通知,自己处理掉呢?答案当然是可以的,在 Rxjava 中很多操作符可用于对 Observable 发射的 onError 通知做出响应或者从错误中恢复。

例如:

吞掉这个错误,切换到一个备用的Observable继续发射数据

吞掉这个错误然后发射默认值

吞掉这个错误并立即尝试重启这个Observable

吞掉这个错误,在一些回退间隔后重启这个Observable

Rxjava中常见的错误处理操作符有如下几类:

onErrorReturn():指示Observable在遇到错误时发射一个特定的数据

onErrorResumeNext():指示Observable在遇到错误时发射一个数据序列

onExceptionResumeNext():指示Observable遇到错误时继续发射数据

retry():指示Observable遇到错误时重试

retryWhen():指示Observable遇到错误时,将错误传递给另一个Observable来决定是否要重新给订阅这个Observable

1. Catch

从 onError 通知中恢复发射数据。

4823a15059dba986d42f27ee4e60bda0.png

Catch 操作符拦截原始Observable的 onError 通知,将它替换为其它的数据项或数据序列,让产生的Observable能够正常终止或者根本不终止。

1.1 onErrorReturn

onErrorReturn 方法返回一个镜像原有Observable行为的新Observable,后者会忽略前者的 onError 调用,不会将错误传递给观察者,作为替代,它会发发射一个特殊的项并调用观察者的 onCompleted 方法。

onErrorReturnItem(T item): 让Observable遇到错误时发射一个指定的项(item)并且正常终止。

8f4ac8770c856297d61becb0b65fdce5.png

onErrorReturn(Function valueSupplier):让Observable遇到错误时通过一个函数Function来进行判断返回指定的类型数据,并且正常终止。

4dba19362b2dafd6e4067960d0282f96.png

示例代码:

// 创建一个可以发射异常的Observable

Observable observable = Observable.create(new ObservableOnSubscribe() {

@Override

public void subscribe(ObservableEmitter emitter) throws Exception {

emitter.onNext(1);

emitter.onNext(2);

emitter.onNext(1 / 0); // 产生一个异常

emitter.onNext(3);

emitter.onNext(4);

}

});

/** 1. onErrorReturnItem(T item)

* 让Observable遇到错误时发射一个指定的项(item)并且正常终止。

*/

observable.onErrorReturnItem(888) // 源Observable发生异常时发射指定的888数据

.subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

System.out.println("--> onSubscribe(1)");

}

@Override

public void onNext(Integer integer) {

System.out.println("--> onNext(1): " + integer);

}

@Override

public void onError(Throwable e) {

System.out.println("--> onError(1): " + e);

}

@Override

public void onComplete() {

System.out.println("--> onCompleted(1)");

}

});

System.out.println("-----------------------------------------------");

/**

* 2. onErrorReturn(Function valueSupplier)

* 让Observable遇到错误时通过一个函数Function来接受Error参数并进行判断返回指定的类型数据,并且正常终止。

*/

observable.onErrorReturn(new Function() {

@Override

public Integer apply(Throwable throwable) throws Exception {

System.out.println("--> apply(1): e = " + throwable);

return 888; // 源Observable发生异常时发射指定的888数据

}

}).subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

System.out.println("--> onSubscribe(2)");

}

@Override

public void onNext(Integer integer) {

System.out.println("--> onNext(2): " + integer);

}

@Override

public void onError(Throwable e) {

System.out.println("--> onError(2): " + e);

}

@Override

public void onComplete() {

System.out.println("--> onCompleted(2)");

}

});

输出:

--> onSubscribe(1)

--> onNext(1): 1

--> onNext(1): 2

--> onNext(1): 888

--> onCompleted(1)

-----------------------------------------------

--> onSubscribe(2)

--> onNext(2): 1

--> onNext(2): 2

--> apply(1): e = java.lang.ArithmeticException: / by zero

--> onNext(2): 888

--> onCompleted(2)

1.2 onErrorResumeNext

onErrorResumeNext 方法返回一个镜像原有Observable行为的新Observable,后者会忽略前者的 onError 调用,不会将错误传递给观察者,作为替代,它会开始另一个指定的备用Observable。

f153162a514dc60878b4c995fc323b85.png

onErrorResumeNext(ObservableSource next): 让Observable在遇到错误时开始发射第二个指定的Observable的数据序列。

onErrorResumeNext(Function resumeFunction):让Observable在遇到错误时通过一个函数Function来接受Error参数并进行判断返回指定的第二个Observable的数据序列。

示例代码:

// 创建一个可以发射异常的Observable

Observable observable = Observable.create(new ObservableOnSubscribe() {

@Override

public void subscribe(ObservableEmitter emitter) throws Exception {

emitter.onNext(1);

emitter.onNext(2);

emitter.onNext(1 / 0); // 产生一个异常

emitter.onNext(3);

emitter.onNext(4);

}

});

/**

* 3. onErrorResumeNext(ObservableSource next)

* 让Observable在遇到错误时开始发射第二个指定的Observable的数据序列

*/

observable.onErrorResumeNext(Observable.just(888)) // 当发生异常的时候继续发射此项Observable

.subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

System.out.println("--> onSubscribe(3)");

}

@Override

public void onNext(Integer integer) {

System.out.println("--> onNext(3): " + integer);

}

@Override

public void onError(Throwable e) {

System.out.println("--> onError(3): " + e);

}

@Override

public void onComplete() {

System.out.println("--> onCompleted(3)");

}

});

System.out.println("-----------------------------------------------");

/**

* 4. onErrorResumeNext(Function> resumeFunction)

* 让Observable在遇到错误时通过一个函数Function来接受Error参数并进行判断返回指定的第二个Observable的数据序列

*/

observable.onErrorResumeNext(new Function>() {

@Override

public ObservableSource extends Integer> apply(Throwable throwable) throws Exception {

System.out.println("--> apply(4): " + throwable);

return Observable.just(888); // 当发生异常的时候继续发射此项Observable

}

}).subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

System.out.println("--> onSubscribe(4)");

}

@Override

public void onNext(Integer integer) {

System.out.println("--> onNext(4): " + integer);

}

@Override

public void onError(Throwable e) {

System.out.println("--> onError(4): " + e);

}

@Override

public void onComplete() {

System.out.println("--> onCompleted(4)");

}

});

输出:

--> onSubscribe(3)

--> onNext(3): 1

--> onNext(3): 2

--> onNext(3): 888

--> onCompleted(3)

-----------------------------------------------

--> onSubscribe(4)

--> onNext(4): 1

--> onNext(4): 2

--> apply(4): java.lang.ArithmeticException: / by zero

--> onNext(4): 888

--> onCompleted(4)

1.3 onExceptionResumeNext

与 onErrorResumeNext 类似, onExceptionResumeNext 方法返回一个镜像原有Observable行为的新Observable,也使用一个备用的Observable,不同的是,如果 onError 收到的 Throwable 不是一个 Exception ,它会将错误传递给观察者的 onError 方法,不会使用备用的Observable。

1092438887082090a4f94eefad5e88af.png

解析: onExceptionResumeNext 只会对Exception类型的异常进行处理,如果onError收到的Throwable不是一个Exception,它会将错误传递给观察者的onError方法,不会使用备用的Observable 。

示例代码:

// 创建一个可以发射异常的Observable

Observable observable1 = Observable.create(new ObservableOnSubscribe() {

@Override

public void subscribe(ObservableEmitter emitter) throws Exception {

emitter.onNext(1);

emitter.onNext(2);

// emitter.onError(new Throwable("This is Throwable!")); // Throwable类型异常,直接通知观察者

// emitter.onError(new Error("This is Error!")); // Error类型异常,直接通知观察者

emitter.onError(new Exception("This is Exception!")); // Exception类型异常,进行处理,发送备用的Observable数据

// emitter.onNext(1 / 0); // 会产生一个ArithmeticException异常,异常会被处理,发送备用的Observable数据

emitter.onNext(3);

emitter.onNext(4);

}

});

/**

* 5. onExceptionResumeNext(ObservableSource next)

* 如果onError收到的Throwable不是一个Exception,它会将错误传递给观察者的onError方法,不会使用备用的Observable

* 只对Exception类型的异常通知进行备用Observable处理

*/

observable1.onExceptionResumeNext(Observable.just(888))

.subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

System.out.println("--> onSubscribe(5)");

}

@Override

public void onNext(Integer integer) {

System.out.println("--> onNext(5): " + integer);

}

@Override

public void onError(Throwable e) {

System.out.println("--> onError(5): " + e);

}

@Override

public void onComplete() {

System.out.println("--> onCompleted(5)");

}

});

输出:

--> onSubscribe(5)

--> onNext(5): 1

--> onNext(5): 2

--> onNext(5): 888

--> onCompleted(5)

2. Retry

如果原始Observable遇到错误,重新订阅它期望它能正常终止。

Retry 操作符不会将原始 Observable 的 onError 通知传递给观察者,它会订阅这个Observable,再给它机会无错误地完成它的数据序列。 Retry 总是传递 onNext 通知给观察者,由于重新订阅,可能会造成数据项重复情况。

2.1 retry()

retry():无论收到多少次 onError 通知,无参数版本的 retry 都会继续订阅并发射原始Observable。

f8d759f1b0caaeb08b5398fdff7cd4e2.png

注意: 因为如果遇到异常,将会无条件的重新订阅原始的Observable,知道没有异常的发射全部的数据序列为止。所以如果你的异常发生后重新订阅也不会恢复正常的话,会一直订阅下去,有内存泄露的风险。

2.2 retry(long times)

retry(long times):接受单个 count 参数的 retry 会最多重新订阅指定的次数,如果次数超了,它不会尝试再次订阅,它会把最新的一个 onError 通知传递给它的观察者。

81deaeb349235b4b7043db90eef5e56b.png

2.3 retry(long times, Predicate predicate)

retry(long times, Predicate predicate):遇到异常后最多重新订阅 times 次,每次重新订阅经过函数predicate 最终判断是否继续重新订阅,如果 times 到达上限或者 predicate 返回 false 中任意一个最先满足条件,都会终止重新订阅,retry 会将最新的一个 onError 通知传递给它的观察者。

358c053bad6072539ec3134d1985c238.png

2.4 retry(Predicate predicate)

retry(Predicate predicate):接受一个谓词函数作为参数,这个函数的两个参数是:重试次数和导致发射 onError 通知的 Throwable 。这个函数返回一个布尔值,如果返回 true , retry 应该再次订阅和镜像原始的Observable,如果返回 false , retry 会将最新的一个 onError 通知传递给它的观察者

3d579481106f83c9018a9aa9ef8ce833.png

2.5 retry(BiPredicate predicate)

retry(BiPredicate predicate):遇到异常时,通过函数 predicate 判断是否重新订阅源Observable,并且通过参数 Integer 传递给 predicate 重新订阅的次数,retry 会将最新的一个 onError 通知传递给它的观察者。

a2c75da643cae5978caba2584a054473.png

2.6 retryUntil(BooleanSupplier stop)

retryUntil(BooleanSupplier stop):重试重新订阅,直到给定的停止函数 stop 返回 true,retry 会将最新的一个 onError 通知传递给它的观察者。

f5d84fdedbf57e0c1e29c5a8b25137fb.png

2.7 retryWhen(Function handler)

retryWhen(Function, ObservableSource> handler):retryWhen 和 retry 类似,区别是, retryWhen 将 onError 中的 Throwable 传递给一个函数,这个函数产生另一个 Observable, retryWhen 观察它的结果再决定是不是要重新订阅原始的Observable。如果这个Observable发射了一项数据,它就重新订阅,如果这个Observable发射的是 onError 通知,它就将这个通知传递给观察者然后终止。

08749290e793148fc9312fd561cbd8a3.png

实例代码:

// flag for emitted onError times

public static int temp = 0;

// 创建可以发送Error通知的Observable

Observable observable = Observable.create(new ObservableOnSubscribe() {

@Override

public void subscribe(ObservableEmitter emitter) throws Exception {

emitter.onNext(1);

emitter.onNext(2);

if (temp <= 2) {

emitter.onError(new Exception("Test Error!"));

temp++;

}

emitter.onNext(3);

emitter.onNext(4);

}

});

/**

* 1. retry()

* 无论收到多少次onError通知, 都会去继续订阅并发射原始Observable。

*/

observable.doOnSubscribe(new Consumer() {

@Override

public void accept(Disposable disposable) throws Exception {

System.out.println("----> doOnSubscribe(1)");

}

}).retry().subscribe(new Consumer() {

@Override

public void accept(Integer integer) throws Exception {

System.out.println("--> accept(1): " + integer);

}

});

System.out.println("---------------------------------------------");

temp = 0;

/**

* 2. retry(long times)

* 遇到异常后,最多重新订阅源Observable times次

*/

observable.doOnSubscribe(new Consumer() {

@Override

public void accept(Disposable disposable) throws Exception {

System.out.println("----> doOnSubscribe(2)");

}

}).retry(1) // 遇到异常后,重复订阅的1次

.subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

System.out.println("--> onSubscribe(2)");

}

@Override

public void onNext(Integer integer) {

System.out.println("--> onNext(2): " + integer);

}

@Override

public void onError(Throwable e) {

System.out.println("--> onError(2): " + e);

}

@Override

public void onComplete() {

System.out.println("--> onCompleted(2)");

}

});

System.out.println("---------------------------------------------");

temp = 0;

/**

* 3. retry(long times, Predicate predicate)

* 遇到异常后最多重新订阅times次,每次重新订阅经过函数predicate最终判断是否继续重新订阅

* 如果times到达上限或者predicate返回false中任意一个最先满足条件,都会终止重新订阅

*/

observable.doOnSubscribe(new Consumer() {

@Override

public void accept(Disposable disposable) throws Exception {

System.out.println("----> doOnSubscribe(3)");

}

}).retry(2, new Predicate() {

@Override

public boolean test(Throwable throwable) throws Exception {

System.out.println("--> test(3)");

if(throwable instanceof Exception) {

return true; // 遇到异常通知后是否继续继续订阅

}

return false;

}

}).subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

System.out.println("--> onSubscribe(3)");

}

@Override

public void onNext(Integer integer) {

System.out.println("--> onNext(3): " + integer);

}

@Override

public void onError(Throwable e) {

System.out.println("--> onError(3): " + e);

}

@Override

public void onComplete() {

System.out.println("--> onCompleted(3)");

}

});

System.out.println("---------------------------------------------");

temp = 0;

/**

* 4. retry(Predicate predicate)

* 遇到异常时,通过函数predicate判断是否重新订阅源Observable

*/

observable.doOnSubscribe(new Consumer() {

@Override

public void accept(Disposable disposable) throws Exception {

System.out.println("----> doOnSubscribe(4)");

}

}).retry(new Predicate() {

@Override

public boolean test(Throwable throwable) throws Exception {

if (throwable instanceof Exception) {

return true; // 遇到异常通知后是否继续继续订阅

}

return false;

}

}).subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

System.out.println("--> onSubscribe(4)");

}

@Override

public void onNext(Integer integer) {

System.out.println("--> onNext(4): " + integer);

}

@Override

public void onError(Throwable e) {

System.out.println("--> onError(4): " + e);

}

@Override

public void onComplete() {

System.out.println("--> onCompleted(4)");

}

});

System.out.println("---------------------------------------------");

temp = 0;

/**

* 5. retry(BiPredicate predicate)

* 遇到异常时,通过函数predicate判断是否重新订阅源Observable,并且通过参数integer传递给predicate重新订阅的次数

*/

observable.doOnSubscribe(new Consumer() {

@Override

public void accept(Disposable disposable) throws Exception {

System.out.println("----> doOnSubscribe(5)");

}

}).retry(new BiPredicate() {

@Override

public boolean test(Integer integer, Throwable throwable) throws Exception {

System.out.println("--> test(5): " + integer);

if (throwable instanceof Exception) {

return true; // 遇到异常通知后是否继续继续订阅

}

return false;

}

}).subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

System.out.println("--> onSubscribe(5)");

}

@Override

public void onNext(Integer integer) {

System.out.println("--> onNext(5): " + integer);

}

@Override

public void onError(Throwable e) {

System.out.println("--> onError(5): " + e);

}

@Override

public void onComplete() {

System.out.println("--> onCompleted(5)");

}

});

System.out.println("---------------------------------------------");

temp = 0;

/**

* 6. retryUntil(BooleanSupplier stop)

* 重试重新订阅,直到给定的停止函数stop返回true

*/

observable.doOnSubscribe(new Consumer() {

@Override

public void accept(Disposable disposable) throws Exception {

System.out.println("----> doOnSubscribe(6)");

}

}).retryUntil(new BooleanSupplier() {

@Override

public boolean getAsBoolean() throws Exception {

System.out.println("--> getAsBoolean(6)");

if(temp == 1){ // 满足条件,停止重新订阅

return true;

}

return false;

}

}).subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

System.out.println("--> onSubscribe(6)");

}

@Override

public void onNext(Integer integer) {

System.out.println("--> onNext(6): " + integer);

}

@Override

public void onError(Throwable e) {

System.out.println("--> onError(6): " + e);

}

@Override

public void onComplete() {

System.out.println("--> onCompleted(6)");

}

});

System.out.println("---------------------------------------------");

temp = 0;

/**

* 7. retryWhen(Function, ObservableSource> handler)

* 将onError中的Throwable传递给一个函数handler,这个函数产生另一个Observable,

* retryWhen观察它的结果再决定是不是要重新订阅原始的Observable。

* 如果这个Observable发射了一项数据,它就重新订阅,

* 如果这个Observable发射的是onError通知,它就将这个通知传递给观察者然后终止。

*/

observable.doOnSubscribe(new Consumer() {

@Override

public void accept(Disposable disposable) throws Exception {

System.out.println("----> doOnSubscribe(7)");

}

}).retryWhen(new Function, ObservableSource>>() {

@Override

public ObservableSource> apply(Observable throwableObservable) throws Exception {

System.out.println("--> apply(7)");

// 根据产生的Error的Observable是否正常发射数据来进行重新订阅,如果发射Error通知,则直接传递给观察者后终止

return throwableObservable.flatMap(new Function>() {

@Override

public ObservableSource> apply(Throwable throwable) throws Exception {

if (temp == 1) {

return Observable.error(throwable); // 满足条件后,传递这个Error,终止重新订阅

}

return Observable.timer(1, TimeUnit.MILLISECONDS); // 正常发射数据,可以重新订阅

}

});

}

}).subscribe(new Observer() {

@Override

public void onSubscribe(Disposable d) {

System.out.println("--> onSubscribe(7)");

}

@Override

public void onNext(Integer integer) {

System.out.println("--> onNext(7): " + integer);

}

@Override

public void onError(Throwable e) {

System.out.println("--> onError(7): " + e);

}

@Override

public void onComplete() {

System.out.println("--> onCompleted(7)");

}

});

System.in.read();

输出:

----> doOnSubscribe(1)

--> accept(1): 1

--> accept(1): 2

----> doOnSubscribe(1)

--> accept(1): 1

--> accept(1): 2

----> doOnSubscribe(1)

--> accept(1): 1

--> accept(1): 2

----> doOnSubscribe(1)

--> accept(1): 1

--> accept(1): 2

--> accept(1): 3

--> accept(1): 4

---------------------------------------------

--> onSubscribe(2)

----> doOnSubscribe(2)

--> onNext(2): 1

--> onNext(2): 2

----> doOnSubscribe(2)

--> onNext(2): 1

--> onNext(2): 2

--> onError(2): java.lang.Exception: Test Error!

---------------------------------------------

--> onSubscribe(3)

----> doOnSubscribe(3)

--> onNext(3): 1

--> onNext(3): 2

--> test(3)

----> doOnSubscribe(3)

--> onNext(3): 1

--> onNext(3): 2

--> test(3)

----> doOnSubscribe(3)

--> onNext(3): 1

--> onNext(3): 2

--> onError(3): java.lang.Exception: Test Error!

---------------------------------------------

--> onSubscribe(4)

----> doOnSubscribe(4)

--> onNext(4): 1

--> onNext(4): 2

----> doOnSubscribe(4)

--> onNext(4): 1

--> onNext(4): 2

----> doOnSubscribe(4)

--> onNext(4): 1

--> onNext(4): 2

----> doOnSubscribe(4)

--> onNext(4): 1

--> onNext(4): 2

--> onNext(4): 3

--> onNext(4): 4

---------------------------------------------

--> onSubscribe(5)

----> doOnSubscribe(5)

--> onNext(5): 1

--> onNext(5): 2

--> test(5): 1

----> doOnSubscribe(5)

--> onNext(5): 1

--> onNext(5): 2

--> test(5): 2

----> doOnSubscribe(5)

--> onNext(5): 1

--> onNext(5): 2

--> test(5): 3

----> doOnSubscribe(5)

--> onNext(5): 1

--> onNext(5): 2

--> onNext(5): 3

--> onNext(5): 4

---------------------------------------------

--> onSubscribe(6)

----> doOnSubscribe(6)

--> onNext(6): 1

--> onNext(6): 2

--> getAsBoolean(6)

----> doOnSubscribe(6)

--> onNext(6): 1

--> onNext(6): 2

--> getAsBoolean(6)

--> onError(6): java.lang.Exception: Test Error!

---------------------------------------------

--> apply(7)

--> onSubscribe(7)

----> doOnSubscribe(7)

--> onNext(7): 1

--> onNext(7): 2

----> doOnSubscribe(7)

--> onNext(7): 1

--> onNext(7): 2

--> onError(7): java.lang.Exception: Test Error!

小结

本节主要介绍了 Rxjava 中关于 Error 通知的处理,主要是在遇到异常通知时,无条件或者指定条件的去重新订阅原始 Observable 直到没有异常(正常发射所有数据序列)或者满足指定的条件后终止重新订阅,发射异常通知给观察者。

提示:以上使用的Rxjava2版本: 2.2.12

Rx介绍与讲解及完整目录参考:Rxjava2 介绍与详解实例

实例代码:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值