RxJava2之错误处理操作符与辅助操作符

471 阅读5分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情

RxJava在出现错误的时候都是调用SubscriberonError方法将错误分发,然后交给Subscriber自己处理,这样就需要我们每个Subscriber都处理一次,就加大了工作量,所以就需要用到错误处理操作符。

错误处理操作符

1.catch

catch操作符能拦截原始ObservableonError通知,并将它替换为其他的数据项或者数据序列。让产生的Observable能够正常终止或者根本不终止。 RxJavacatch实现为以下三个不用的操作符。 onErrorReturn:当Observable遇到错误时发射一个特殊项并正常终止。

catch.png

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的数据序列。 c2.png

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`。

c3.png

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操作符不会将原始ObservableonError发送给观察者,而是重新订阅它期望它能正常终止。 由于重新订阅,可能会造成数据项重复。 retry()会无休止地订阅并发射原始Observable,直到正常终止。 retry(count)可以指定重试次数。如果次数超了,则不会再次订阅。而是将一个新的onError发送个他的观察者。

retry.C.png

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通知。

delay.o.png

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每发射一个数据项都会回调他一次,不论obNextonError还是onCompleted
  • doOnNext 只有onNext执行时才会回调他。
  • doOnSubscribe 当观察者订阅Observable就会被调用。
  • doOnComplete 只有onComplete执行时才会回调他。
  • doOnError 只有onError执行时才会回调他。
  • doOnTerminate Observable终止(不论正常还是异常)前会被调用。
  • doFinally Observable终止(不论正常还是异常)后会被调用。

doOnEach

doOnEach.png doOnSubscribe

doOnSubscribe.png

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: