版權聲明:本文爲openXu原創文章【openXu的博客】,未經博主允許不得以任何形式轉載
目錄:
1. Catch
Catch操作符能夠攔截原始Observable的onError通知,不讓Observable因爲產生錯誤而終止。相當於java中try/catch操作,不能因爲拋異常而導致程序崩潰。 retry操作符默認在trampoline調度器上執行。
RxJava將Catch實現爲三個不同的操作符:
-
onErrorReturn
:onErrorReturn方法返回一個原有Observable行爲的新Observable鏡像,後者會忽略前者的onError調用,不會將錯誤傳遞給觀察者,作爲替代,它會發發射一個特殊的項並調用觀察者的onCompleted方法。- Javadoc: onErrorReturn(Func1)
-
onErrorResumeNext
:讓Observable在遇到錯誤時開始發射第二個Observable的數據序列。 onErrorResumeNext方法返回一個原有Observable行爲的新Observable鏡像 ,後者會忽略前者的onError調用,不會將錯誤傳遞給觀察者,作爲替代,它會開始發射鏡像Observable的數據。- Javadoc: onErrorResumeNext(Func1)
- Javadoc: onErrorResumeNext(Observable)
-
onExceptionResumeNext
: 讓Observable在遇到錯誤時繼續發射後面的數據項。 和onErrorResumeNext類似,onExceptionResumeNext方法返回一個鏡像原有Observable行爲的新Observable,也使用一個備用的Observable,不同的是,如果onError收到的Throwable不是一個Exception,它會將錯誤傳遞給觀察者的onError方法,不會使用備用的Observable。- Javadoc: onExceptionResumeNext(Observable)
示例代碼:
注意:在測試onExceptionResumeNext 的時候,不妨試試onError中發射Throwable的情況,這種情況會將onError通知發送給訂閱者,並停止。
/*
* ①.onErrorReturn:
* 返回一個原有Observable行爲的新Observable鏡像,
* 後者會忽略前者的onError調用,不會將錯誤傳遞給觀察者,
* 作爲替代,它會發發射一個特殊的項並調用觀察者的onCompleted方法
*/
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for(int i = 0;i < 10; i++){
if(i>3){
//會忽略onError調用,不會將錯誤傳遞給觀察者
subscriber.onError(new Throwable("i太大了"));
}
subscriber.onNext(i);
}
subscriber.onCompleted();
}
}).onErrorReturn(new Func1<Throwable, Integer>() {
//作爲替代,它會發發射一個特殊的項並調用觀察者的onCompleted方法。
@Override
public Integer call(Throwable throwable) {
return 10;
}
}).subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
Log.v(TAG, "①onErrorReturn(Func1)->onCompleted");
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "①onErrorReturn(Func1)->onError:"+e.getMessage());
}
@Override
public void onNext(Integer integer) {
Log.v(TAG, "①onErrorReturn(Func1)->onNext:"+integer);
}
});
/*
* ②.onErrorResumeNext(Observable):
* 當原Observable發射onError消息時,會忽略onError消息,不會傳遞給觀察者;
* 然後它會開始另一個備用的Observable,繼續發射數據
*/
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for(int i = 0;i < 10; i++){
if(i>3){
//會忽略onError調用,不會將錯誤傳遞給觀察者
subscriber.onError(new Throwable("i太大了"));
}
subscriber.onNext(i);
}
subscriber.onCompleted();
}
}).onErrorResumeNext(Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for(int i = 10;i < 13; i++){
subscriber.onNext(i);
}
subscriber.onCompleted();
}
})).subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
Log.v(TAG, "②onErrorResumeNext(Observable)->onCompleted");
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "②onErrorResumeNext(Observable)->onError:"+e.getMessage());
}
@Override
public void onNext(Integer integer) {
Log.v(TAG, "②onErrorResumeNext(Observable)->onNext:"+integer);
}
});
/*
* ③.onErrorResumeNext(Func1):
* 和onErrorResumeNext(Observable)相似,但他能截取到原Observable的onError消息
*/
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for(int i = 0;i < 10; i++){
if(i>3){
//會忽略onError調用,不會將錯誤傳遞給觀察者
subscriber.onError(new Throwable("i太大了"));
}
subscriber.onNext(i);
}
subscriber.onCompleted();
}
}).onErrorResumeNext(new Func1<Throwable, Observable<? extends Integer>>() {
@Override
public Observable<? extends Integer> call(Throwable throwable) {
//throwable就是原Observable發射的onError消息中的Throwable對象
Log.e(TAG, "③onErrorResumeNext(Func1)->throwable:"+throwable.getMessage());
//如果原Observable發射了onError消息,將會開啓下面的Observable
return Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for(int i = 100;i < 103; i++){
subscriber.onNext(i);
}
subscriber.onCompleted();
}
});
}
}).subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
Log.v(TAG, "③onErrorResumeNext(Func1)->onCompleted");
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "③onErrorResumeNext(Func1)->onError:"+e.getMessage());
}
@Override
public void onNext(Integer integer) {
Log.v(TAG, "onErrorResumeNext(Func1)->onNext:"+integer);
}
});
/*
* ④.onExceptionResumeNext:
* 和onErrorResumeNext類似,可以說是onErrorResumeNext的特例,
* 區別是如果onError收到的Throwable不是一個Exception,它會將錯誤傳遞給觀察者的onError方法,不會使用備用的Observable。
*/
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for(int i = 0;i < 10; i++){
if(i>3){
//如果不是Exception,錯誤會傳遞給觀察者,不會開啓備用Observable
//subscriber.onError(new Throwable("i太大了"));
//如果Exception,不會將錯誤傳遞給觀察者,並會開啓備用Observable
subscriber.onError(new Exception("i太大了哦哦哦"));
}
subscriber.onNext(i);
}
subscriber.onCompleted();
}
}).onExceptionResumeNext(Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for(int i = 10;i < 13; i++){
subscriber.onNext(i);
}
subscriber.onCompleted();
}
})).subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
Log.v(TAG, "④onExceptionResumeNext(Observable)->onCompleted");
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "④onExceptionResumeNext(Observable)->onError:"+e.getClass().getSimpleName()+":"+e.getMessage());
}
@Override
public void onNext(Integer integer) {
Log.v(TAG, "④onExceptionResumeNext(Observable)->onNext:"+integer);
}
});
輸出:
①onErrorReturn(Func1)->onNext:0
①onErrorReturn(Func1)->onNext:1
①onErrorReturn(Func1)->onNext:2
①onErrorReturn(Func1)->onNext:3
①onErrorReturn(Func1)->onNext:10
①onErrorReturn(Func1)->onCompleted
②onErrorResumeNext(Observable)->onNext:0
②onErrorResumeNext(Observable)->onNext:1
②onErrorResumeNext(Observable)->onNext:2
②onErrorResumeNext(Observable)->onNext:3
②onErrorResumeNext(Observable)->onNext:10
②onErrorResumeNext(Observable)->onNext:11
②onErrorResumeNext(Observable)->onNext:12
②onErrorResumeNext(Observable)->onCompleted
③onErrorResumeNext(Func1)->onNext:0
③onErrorResumeNext(Func1)->onNext:1
③onErrorResumeNext(Func1)->onNext:2
③onErrorResumeNext(Func1)->onNext:3
③onErrorResumeNext(Func1)->throwable:i太大了
③onErrorResumeNext(Func1)->onNext:100
③onErrorResumeNext(Func1)->onNext:101
③onErrorResumeNext(Func1)->onNext:102
③onErrorResumeNext(Func1)->onCompleted
④onExceptionResumeNext(Observable)->onNext:0
④onExceptionResumeNext(Observable)->onNext:1
④onExceptionResumeNext(Observable)->onNext:2
④onExceptionResumeNext(Observable)->onNext:3
④onExceptionResumeNext(Observable)->onNext:10
④onExceptionResumeNext(Observable)->onNext:11
④onExceptionResumeNext(Observable)->onNext:12
④onExceptionResumeNext(Observable)->onCompleted
2. Retry
顧名思義,retry的意思就是試着重來,當原始Observable發射onError通知時,retry操作符不會讓onError通知傳遞給觀察者,它會重新訂閱這個Observable一次或者多次(意味着重新從頭髮射數據),所以可能造成數據項重複發送的情況。
如果重新訂閱了指定的次數還是發射了onError通知,將不再嘗試重新訂閱,它會把最新的一個onError通知傳遞給觀察者。
RxJava中將Retry操作符的實現爲retry和retryWhen兩種:
- retry:
-
Javadoc: retry():無論收到多少次onError通知,都會繼續訂閱並重發原始Observable,直到onCompleted。
-
Javadoc: retry(long):接受count參數的retry會最多重新訂閱count次,如果次數超過了就不會嘗試再次訂閱,它會把最新的一個onError通知傳遞給他的觀察者。
-
Javadoc: retry(Func2): 這個版本的retry接受一個謂詞函數作爲參數,這個函數的兩個參數是:重試次數和導致發射onError通知的Throwable。這個函數返回一個布爾值,如果返回true,retry應該再次訂閱和鏡像原始的Observable,如果返回false,retry會將最新的一個onError通知傳遞給它的觀察者。
-
示例代碼:
/**
* ①. retry()
* 無限次嘗試重新訂閱
*/
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for(int i = 0; i<3; i++){
if(i==1){
Log.v(TAG, "①retry()->onError");
subscriber.onError(new RuntimeException("always fails"));
}else{
subscriber.onNext(i);
}
}
}
}).retry() //無限次嘗試重新訂閱
.subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
Log.v(TAG, "①retry()->onCompleted");
}
@Override
public void onError(Throwable e) {
Log.v(TAG, "①retry()->onError"+e.getMessage());
}
@Override
public void onNext(Integer i) {
Log.v(TAG, "①retry()->onNext"+i);
}
});
/**
* ②. retry(count)
* 最多2次嘗試重新訂閱
*/
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for(int i = 0; i<3; i++){
if(i==1){
Log.v(TAG, "②retry(count)->onError");
subscriber.onError(new RuntimeException("always fails"));
}else{
subscriber.onNext(i);
}
}
}
}).retry(2) //最多嘗試2次重新訂閱
.subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
Log.v(TAG, "②retry(count)->onCompleted");
}
@Override
public void onError(Throwable e) {
Log.v(TAG, "②retry(count)->onError"+e.getMessage());
}
@Override
public void onNext(Integer i) {
Log.v(TAG, "②retry(count)->onNext"+i);
}
});
/**
* ③. retry(Func2)
*/
Observable.create(new Observable.OnSubscribe<Integer>() {
@Override
public void call(Subscriber<? super Integer> subscriber) {
for(int i = 0; i<3; i++){
if(i==1){
Log.v(TAG, "③retry(Func2)->onError");
subscriber.onError(new RuntimeException("always fails"));
}else{
subscriber.onNext(i);
}
}
}
}).retry(new Func2<Integer, Throwable, Boolean>() {
@Override
public Boolean call(Integer integer, Throwable throwable) {
Log.v(TAG, "③發生錯誤了:"+throwable.getMessage()+",第"+integer+"次重新訂閱");
if(integer>2){
return false;//不再重新訂閱
}
//此處也可以通過判斷throwable來控制不同的錯誤不同處理
return true;
}
}).subscribe(new Subscriber<Integer>() {
@Override
public void onCompleted() {
Log.v(TAG, "③retry(Func2)->onCompleted");
}
@Override
public void onError(Throwable e) {
Log.v(TAG, "③retry(Func2)->onError"+e.getMessage());
}
@Override
public void onNext(Integer i) {
Log.v(TAG, "③retry(Func2)->onNext"+i);
}
});
輸出:
①retry()->onNext0
①retry()->onError
①retry()->onNext0
①retry()->onError
…無限次
②retry(count)->onNext0
②retry(count)->onError
②retry(count)->onNext0
②retry(count)->onError
②retry(count)->onNext0
②retry(count)->onError
②retry(count)->onErroralways fails
③retry(Func2)->onNext0
③retry(Func2)->onError
③發生錯誤了:always fails,第1次重新訂閱
③retry(Func2)->onNext0
③retry(Func2)->onError
③發生錯誤了:always fails,第2次重新訂閱
③retry(Func2)->onNext0
③retry(Func2)->onError
③發生錯誤了:always fails,第3次重新訂閱
③retry(Func2)->onErroralways fails
- retryWhen:
retryWhen和retry類似,區別是,retryWhen將onError中的Throwable傳遞給一個函數,這個函數產生另一個Observable,retryWhen觀察它的結果再決定是不是要重新訂閱原始的Observable。如果這個Observable發射了一項數據,它就重新訂閱,如果這個Observable發射的是onError通知,它就將這個通知傳遞給觀察者然後終止。
示例代碼:
Observable.create((Subscriber<? super String> s) -> {
System.out.println("subscribing");
s.onError(new RuntimeException("always fails"));
}).retryWhen(attempts -> {
return attempts.zipWith(Observable.range(1, 3), (n, i) -> i).flatMap(i -> {
System.out.println("delay retry by " + i + " second(s)");
return Observable.timer(i, TimeUnit.SECONDS);
});
}).toBlocking().forEach(System.out::println);
輸出:
**有問題請留言,有幫助請點贊(^__^)**subscribing
delay retry by 1 second(s)
subscribing
delay retry by 2 second(s)
subscribing
delay retry by 3 second(s)
subscribing
#源碼下載: