一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
RxJava在出现错误的时候都是调用Subscriber
的onError
方法将错误分发,然后交给Subscriber
自己处理,这样就需要我们每个Subscriber
都处理一次,就加大了工作量,所以就需要用到错误处理操作符。
错误处理操作符
1.catch
catch
操作符能拦截原始Observable
的onError
通知,并将它替换为其他的数据项或者数据序列。让产生的Observable
能够正常终止或者根本不终止。
RxJava
将catch
实现为以下三个不用的操作符。
onErrorReturn:当Observable
遇到错误时发射一个特殊项并正常终止。
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onError(new Exception("ex"));
emitter.onNext(3);
emitter.onComplete();
}
}).onErrorReturn(new Function<Throwable, Integer>() {
@Override
public Integer apply(Throwable throwable) throws Exception {
return -1;
}
}).subscribe(new Observer<Integer>() {
public void onSubscribe(Disposable d) {
}
public void onNext(Integer integer) {
Log.i(TAG, "onNext: "+integer);
}
public void onError(Throwable e) {
Log.i(TAG, "onError: "+e.getMessage());
}
public void onComplete() {
Log.i(TAG, "onComplete: ");
}
});
输出结果如下
I/TAG: onNext: 1
I/TAG: onNext: 2
I/TAG: onNext: -1
I/TAG: onComplete:
onErrorResumeNext:当Observable
遇到错误时发射另一个Observable
的数据序列。
final Observable o = Observable.just(10,20,30);
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onError(new Exception("ex"));
emitter.onNext(3);
emitter.onComplete();
}
}).onErrorResumeNext(new Function<Throwable, ObservableSource<? extends Integer>>() {
@Override
public ObservableSource<? extends Integer> apply(Throwable throwable) throws Exception {
return o;
}
}).subscribe(new Observer<Integer>() {
public void onSubscribe(Disposable d) {
}
public void onNext(Integer integer) {
Log.i(TAG, "onNext: "+integer);
}
public void onError(Throwable e) {
Log.i(TAG, "onError: "+e.getMessage());
}
public void onComplete() {
Log.i(TAG, "onComplete: ");
}
});
输出结果如下
I/TAG: onNext: 1
I/TAG: onNext: 2
I/TAG: onNext: 10
I/TAG: onNext: 20
I/TAG: onNext: 30
I/TAG: onComplete:
onExceptionResumeNext:与onErrorResumeNext
类似,不过当onError
收到的是Throwable
不是一个Exception
,它会将错误传递给观察者的onError
方法,不会使用备用的
Observable`。
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onError(new Exception("ex"));
emitter.onNext(3);
emitter.onComplete();
}
}).onExceptionResumeNext(new ObservableSource<Integer>() {
@Override
public void subscribe(Observer<? super Integer> observer) {
observer.onNext(10000);
observer.onComplete();
}
}).subscribe(new Observer<Integer>() {
public void onSubscribe(Disposable d) {
}
public void onNext(Integer integer) {
Log.i(TAG, "onNext: "+integer);
}
public void onError(Throwable e) {
Log.i(TAG, "onError: "+e.getMessage());
}
public void onComplete() {
Log.i(TAG, "onComplete: ");
}
});
输出结果如下
I/TAG: onNext: 1
I/TAG: onNext: 2
I/TAG: onNext: 10000//错误替换的消息
I/TAG: onComplete:
如果收到的Throwable不是一个Exception,则会输出如下结果,即onExceptionResumeNext
不能拦截Throwable
I/TAG: onNext: 1
I/TAG: onNext: 2
I/TAG: onError: ex
2.retry
retry
操作符不会将原始Observable
的onError
发送给观察者,而是重新订阅它期望它能正常终止。
由于重新订阅,可能会造成数据项重复。
retry()
会无休止地订阅并发射原始Observable
,直到正常终止。
retry(count)
可以指定重试次数。如果次数超了,则不会再次订阅。而是将一个新的onError
发送个他的观察者。
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onError(new Throwable("ex"));
emitter.onNext(3);
emitter.onComplete();
}
}).retry(1).subscribe(new Observer<Integer>() {
public void onSubscribe(Disposable d) {
}
public void onNext(Integer integer) {
Log.i(TAG, "onNext: "+integer);
}
public void onError(Throwable e) {
Log.i(TAG, "onError: "+e.getMessage());
}
public void onComplete() {
Log.i(TAG, "onComplete: ");
}
});
输出结果如下
I/TAG: onNext: 1
I/TAG: onNext: 2
I/TAG: onNext: 1
I/TAG: onNext: 2
I/TAG: onError: ex
辅助操作符
1.delay
delay
操作符可以让原始Observable
在发射每项数据之前都先暂停一段时间,即Observable
发射的数据项在时间上都向前整体平移一个增量。每当原始Observable
发射一个数据项,delay
就启动一个定时器,当过了定时器指定的时间,delay
返回的Observable
发射相同的数据项。
注意:delay
不会平移onError
通知。他会立即将这个通知传递个订阅者,同时丢弃onNext通知。
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onError(new Throwable("Throwable"));
emitter.onNext(3);
}
}).delay(10, TimeUnit.SECONDS)//延时10s
.subscribe(new Observer<Integer>() {
public void onSubscribe(Disposable d) {
Log.i(TAG, "satrtTime: "+System.currentTimeMillis());
}
public void onNext(Integer integer) {
Log.i(TAG, "endTime-onNext: "+System.currentTimeMillis()+" "+integer);
}
public void onError(Throwable e) {
Log.i(TAG, "endTime-onError: "+System.currentTimeMillis()+" "+e);
}
public void onComplete() {
Log.i(TAG, "endTime-onComplete: "+System.currentTimeMillis());
}
});
输出结果如下:
I/TAGTAG: satrtTime: 1524668052808
I/TAGTAG: endTime-onError: 1524668052812 java.lang.Throwable: Throwable //(endTime-satrtTime)小与10s
2.do
do
操作符为原始Observable
生命周期事件注册一个回调,当某个事件触发时就会执行这些回调。do
操作符包含以下操作符:
- doOnEach
Observable
每发射一个数据项都会回调他一次,不论obNext
,onError
还是onCompleted
。 - doOnNext 只有
onNext
执行时才会回调他。 - doOnSubscribe 当观察者订阅
Observable
就会被调用。 - doOnComplete 只有
onComplete
执行时才会回调他。 - doOnError 只有
onError
执行时才会回调他。 - doOnTerminate
Observable
终止(不论正常还是异常)前会被调用。 - doFinally
Observable
终止(不论正常还是异常)后会被调用。
doOnEach
doOnSubscribe
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onError(new Throwable("throw"));
// emitter.onComplete();
}
}).doOnEach(new Consumer<Notification<Integer>>() {
@Override
public void accept(Notification<Integer> integerNotification) throws Exception {
Log.i(TAG, "doOnEach: "+integerNotification);
}
}).doOnNext(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i(TAG, "doOnNext: "+integer);
}
}).doOnComplete(new Action() {
@Override
public void run() throws Exception {
Log.i(TAG, "doOnComplete: ");
}
}).doOnError(new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
Log.i(TAG, "doOnError: "+throwable.getMessage());
}
}).doOnTerminate(new Action() {
@Override
public void run() throws Exception {
Log.i(TAG, "doOnTerminate: ");
}
}).doFinally(new Action() {
@Override
public void run() throws Exception {
Log.i(TAG, "doFinally: ");
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i(TAG, "subscribe: "+integer);
}
});
输出结果如下:
I/TAGTAG: doOnEach: OnNextNotification[1]
I/TAGTAG: doOnNext: 1
I/TAGTAG: subscribe: 1
I/TAGTAG: doOnEach: OnNextNotification[2]
I/TAGTAG: doOnNext: 2
I/TAGTAG: subscribe: 2
I/TAGTAG: doOnEach: OnErrorNotification[java.lang.Throwable: throw]
I/TAGTAG: doOnError: throw
I/TAGTAG: doOnTerminate:
可以看到doOnEach无论是onNext还是onError都会触发他,但是此处doFinally并没有执行,与描述有误,待研究。
3.subscribeOn/observeOn
- subscribeOn用于指定事件产生的线程。
- observeOn用于指定事件消费的线程。
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
Log.i(TAG, "subscribeOn: " +Thread.currentThread().getName());
emitter.onNext(1);
}})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
Log.i(TAG, "observeOn: " +Thread.currentThread().getName());
}
});
输出结果为:
I/TAGTAG: subscribeOn: RxCachedThreadScheduler-1
I/TAGTAG: observeOn: main
4.timeout
如果原始Observable
过了指定事件还没有发射任何数据。timeout
操作符会抛出TimeoutException
,并以一个onError
通知终止这个Observable
。
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
for (int i=0;i<3;i++){
if(i == 1){
SystemClock.sleep(3000);
}else {
emitter.onNext(i);
}
}
}
}).timeout(2,TimeUnit.SECONDS)
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
public void onNext(Integer integer) {
Log.i(TAG, "onNext: "+integer);
}
public void onError(Throwable e) {
Log.i(TAG, "onError: ");
}
public void onComplete() {
}
});
输出结果为:
I/TAGTAG: onNext: 0
I/TAGTAG: onError: