错误处理操作符
错误处理操作符主要是在Observable的onError中拦截,做一些事情。
catch操作符
onErrorReturn
让Observable遇到错误时候发生一个特殊的数据并且正常终止,比如
Observable.just(1, 2, 3, 4, 5).map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
if (integer == 4) {
throw new IllegalArgumentException("hahaha");
}
return integer + "str";
}
}).onErrorReturn(new Func1<Throwable, String>() {
@Override
public String call(Throwable throwable) {
Log.i(TAG, throwable.getMessage());
return "Bingo";
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.i(TAG, "Result == " + s);
}
});
输出结果:
10-26 13:25:46.623 19493-19493/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: Result == 1str
10-26 13:25:46.623 19493-19493/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: Result == 2str
10-26 13:25:46.623 19493-19493/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: Result == 3str
10-26 13:25:46.623 19493-19493/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: hahaha
10-26 13:25:46.633 19493-19493/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: Result == Bingo
说明:onErrorReturn操作符他会拦截错误,然后在拦截错误之后,不再继续发射源Observable的数据,同时,他将在Func1中返回一个对应的可被观测的数据传递到onNext中,然后调用了onComplete方法完成这一次的Observable过程。
onErrorResumeNext
让Observable遇到错误时开始发射第二个Observable数据序列,例子
Observable<String> observable = Observable.just(1, 2, 3, 4, 5).map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
if (integer == 4) {
throw new IllegalArgumentException("hahaha");
}
return integer + "str";
}
});
observable.onErrorResumeNext(new Func1<Throwable, Observable<? extends String>>() {
@Override
public Observable<? extends String> call(Throwable throwable) {
return Observable.just("Bingo","Hello");
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.i(TAG, "onErrorResumeNext == " + s);
}
});
结果:
10-26 13:40:56.843 5987-5987/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onErrorResumeNext == 1str
10-26 13:40:56.843 5987-5987/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onErrorResumeNext == 2str
10-26 13:40:56.843 5987-5987/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onErrorResumeNext == 3str
10-26 13:40:56.843 5987-5987/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onErrorResumeNext == Bingo
10-26 13:40:56.843 5987-5987/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onErrorResumeNext == Hello
可以看到他是终止了继续发射,但是他可以补充发射,就是在遇到错误的时候,可以在源Observable基础上面继续发射多个Observable直到结束。
他的重载函数:
Observable<T> onErrorResumeNext(final Observable<? extends T> resumeSequence)
使用也是类似,他也是可以在遇到错误之后发射多个Observable。
onExceptionResumeNext
让Observable遇到错误时发射继续发射后面的数据项,例子
Observable<String> observable = Observable.just(1, 2, 3, 4, 5).map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
if (integer == 4) {
throw new Error("hahaha");
}
return integer + "str";
}
});
observable.onExceptionResumeNext(Observable.just("A", "B")).subscribe(new Observer<String>() {
@Override
public void onCompleted() {
Log.i(TAG, "onCompleted");
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onError"+e.getMessage());
}
@Override
public void onNext(String s) {
Log.i(TAG, "onNext"+s);
}
});
输出:
10-26 13:49:21.803 16041-16041/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onNext1str
10-26 13:49:21.803 16041-16041/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onNext2str
10-26 13:49:21.803 16041-16041/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onNext3str
10-26 13:49:21.813 16041-16041/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onErrorhahaha
加入不是抛出Error,而是Exception的子类的时候,则结果是:
10-26 13:50:57.643 17881-17881/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onNext1str
10-26 13:50:57.643 17881-17881/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onNext2str
10-26 13:50:57.643 17881-17881/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onNext3str
10-26 13:50:57.643 17881-17881/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onNextA
10-26 13:50:57.643 17881-17881/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onNextB
10-26 13:50:57.643 17881-17881/fortunetelling.mmc.oms.rxjavademo I/MainActivityLOG: onCompleted
说明onExceptionResumeNext操作符是在上级源Observable出现的是Exception的子类的时候调用他自己的Observable继续发射下去,同时是不回再去发射源Observable的数据。但是假如上级源Observable出现的不是Exception的子类的时候,那么他会直接调用onError方法结束发射。
对应的图:
onErrorReturn:
onErrorResumeNext:
onExceptionResumeNext:
retry操作符
retry操作符不会把错误传递到Observer的onError当中去。他可以不停的retry,尝试能够让源Observable正常发射结束。
retry 操作符
他会在源Observable在发生error的时候不断的重新去调用源数据,重头开始发射,存在了数据可能重复的结果,例如:
Observable<String> observable = Observable.range(10, 3).map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
if(integer == 11){
throw new IllegalArgumentException("exception");
}
return integer.toString() + "retry";
}
});
observable.retry().subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.i(TAG, s);
}
});
结果是不断的打印
10retry
重载函数:
Observable<T> retry(final long count)
他可以设置重试次数,超出重试次数之后任然发生错误,那么他将会调用onError方法,例子:
Observable<String> observable = Observable.range(10, 3).map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
if(integer == 11){
throw new IllegalArgumentException("exception");
}
return integer.toString() + "retry";
}
});
observable.retry(2).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.i(TAG, s);
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
Log.i(TAG, throwable.getMessage());
}
});
输出:
10-26 14:22:50.137 4099-4099/com.example.user.testproject I/RxJavaTest: 10retry
10-26 14:22:50.138 4099-4099/com.example.user.testproject I/RxJavaTest: 10retry
10-26 14:22:50.138 4099-4099/com.example.user.testproject I/RxJavaTest: 10retry
10-26 14:22:50.138 4099-4099/com.example.user.testproject I/RxJavaTest: exception
重载函数
retry(Func2<Integer, Throwable, Boolean> predicate)
他可以设定某种界限,在不超出某个条件之下不断的重试,或者说只要是返回了true都会重试,反之停止,停止之后还是发生了错误,就会调用onError方法,例如
Observable<String> observable = Observable.range(10, 3).map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
if(integer == 11){
throw new IllegalArgumentException("exception");
}
return integer.toString() + "retry";
}
});
observable.retry(new Func2<Integer, Throwable, Boolean>() {
@Override
public Boolean call(Integer integer, Throwable throwable) {
return integer<3;
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.i(TAG, s);
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
Log.i(TAG, throwable.getMessage());
}
});
他的意思是,在重试次数少于3的时候就会重试,否则就不会,输出:
10-26 14:28:34.882 8577-8577/com.example.user.testproject I/RxJavaTest: 10retry
10-26 14:28:34.883 8577-8577/com.example.user.testproject I/RxJavaTest: 10retry
10-26 14:28:34.883 8577-8577/com.example.user.testproject I/RxJavaTest: 10retry
10-26 14:28:34.883 8577-8577/com.example.user.testproject I/RxJavaTest: exception
图:
retryWhen
Observable<String> observable = Observable.range(10, 3).map(new Func1<Integer, String>() {
@Override
public String call(Integer integer) {
if(integer == 11){
throw new IllegalArgumentException("exception");
}
return integer.toString() + "retry";
}
});
observable.retryWhen(new Func1<Observable<? extends Throwable>, Observable<?>>() {
@Override
public Observable<?> call(Observable<? extends Throwable> observable) {
return observable.zipWith(Observable.range(1, 3), new Func2<Throwable, Integer, Object>() {
@Override
public Object call(Throwable throwable, Integer integer) {
return "123";
}
});
}
}).subscribe(new Action1<String>() {
@Override
public void call(String s) {
Log.i(TAG, s);
}
}, new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
Log.i(TAG, throwable.getMessage());
}
});
输出:
10-26 15:06:44.358 26227-26227/com.example.user.testproject I/RxJavaTest: 10retry
10-26 15:06:44.359 26227-26227/com.example.user.testproject I/RxJavaTest: 10retry
10-26 15:06:44.359 26227-26227/com.example.user.testproject I/RxJavaTest: 10retry
说明:这里使用了zipWith限制了retryWhen的次数,当超出了三次之后,zipWith回隐式的调用onComplete方法,所以这里的Observer的onError方法并不会被调用。
例子来源:【译】对RxJava中.repeatWhen()和.retryWhen()操作符的思考
关于:
Observable<T> retryWhen(final Func1<? super Observable<? extends Throwable>, ? extends Observable<?>> notificationHandler)
中的notificationHandler的Observable返回说明:
– 如果返回的 Observable 发射了一个数据,retryWhen 将会执行重试操作
– 如果返回的 Observable 发射了一个错误信息,retryWhen 将会发射一个错误并不会重试
– 如果返回的 Observable 正常结束了,retryWhen 也正常结束。
出处:RxJava 教程第三部分:驯服数据流之 高级错误处理
也就是说,其实retryWhen的Func1返回的Observable的值并不重要,是他的类型重要,他只是判断是否可以继续执行retryWhen,例如:
Observable<Integer> source = Observable.create(o -> {
o.onNext(1);
o.onNext(2);
o.onError(new Exception("Failed"));
});
source.retryWhen((o) -> o
.take(2)
.delay(100, TimeUnit.MILLISECONDS))
.timeInterval()
.subscribe(
System.out::println,
System.out::println);
结果:
TimeInterval [intervalInMilliseconds=21, value=1]
TimeInterval [intervalInMilliseconds=0, value=2]
TimeInterval [intervalInMilliseconds=104, value=1]
TimeInterval [intervalInMilliseconds=0, value=2]
TimeInterval [intervalInMilliseconds=103, value=1]
TimeInterval [intervalInMilliseconds=0, value=2]
出处:RxJava 教程第三部分:驯服数据流之 高级错误处理
图:
他还有一个重载的操作符可以指定调度器Scheduler
Observable<T> retryWhen(final Func1<? super Observable<? extends Throwable>, ? extends Observable<?>> notificationHandler, Scheduler scheduler)