错误处理运算符

有助于从Observable中恢复错误通知的操作符。Rx错误处理有两个类别的运算符:

Catch类:Catch运算符拦截来自源Observable的onError通知,而不是将其传递给任何观察者,将其替换为其他项目或项目序列,可能允许生成的Observable正常终止或根本不终止;

Retry类:如果源Observable发出错误,请重新订阅它,希望它能完成而不会出错。重试操作符通过不将该调用传递给其观察者来响应来自源Observable的onError通知,而是通过重新订阅源Observable并为其提供另一个机会来完成其序列而不会出现错误。 重试始终将下一个通知传递给其观察者,即使是以错误终止的序列,因此这会导致重复发射

Rx中有几个常见的Catch类的操作符:onErrorReturn,onErrorResumeNext,onExceptionResumeNext。
Rx中也有几个常见的Retry类的操作符:retry,retryWhen。

我们这里来一一看下:

onErrorReturn

指示Observable在遇到错误时发出特定项,然后正常终止。

android rxjava 调用接口 android rxjava操作符_ide


onErrorReturn运算符,当源Observable发射出onError时,拦截异常并返回一个自定义的值之后正常的结束发射。

举个例子

private void doSomeWork() {
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> observableEmitter) throws Exception {
                observableEmitter.onNext("1");
                observableEmitter.onNext("2");
                observableEmitter.onError(new Throwable("error"));
                observableEmitter.onNext("3");
                observableEmitter.onComplete();

            }
        }).onErrorReturn(new Function<Throwable, String>() {
            @Override
            public String apply(Throwable throwable) throws Exception {
                Log.d(TAG, " apply : " + throwable.getMessage());
                return "onErrorReturn";
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable disposable) {

            }

            @Override
            public void onNext(String s) {
                Log.d(TAG, " onNext : s : " + s);
            }

            @Override
            public void onError(Throwable throwable) {
                Log.d(TAG, " onError : " + throwable.getMessage());
            }

            @Override
            public void onComplete() {
                Log.d(TAG, " onComplete ");
            }
        });
    }

当源发射2后发射了error,会先触发onErrorReturn里的方法,所以打印了error,onErrorReturn拦截并通过Func返回一个值后正常结束发射,所以打印结果

onNext : s : 1
onNext : s : 2
apply : error
onNext : s : onErrorReturn
onComplete

onErrorResumeNext

源Observable在遇到错误时开始发出第二个Observable序列。

android rxjava 调用接口 android rxjava操作符_操作符_02


onErrorResumeNext方法与onErrorReturn()方法类似,都是拦截源Observable发射的onError通知。不同的是onErrorReturn拦截并返回一个自定义的值,而onErrorResumeNext拦截并返回一个新的Observable,并继续接收新的Observable发射的数据。

将上方例子稍作更改:

private void doSomeWork() {
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> observableEmitter) throws Exception {
                observableEmitter.onNext("1");
                observableEmitter.onNext("2");
                observableEmitter.onError(new Throwable("error"));
                observableEmitter.onNext("3");
                observableEmitter.onComplete();

            }
        }).onErrorResumeNext(new Function<Throwable, ObservableSource<? extends String>>() {
            @Override
            public ObservableSource<? extends String> apply(Throwable throwable) throws Exception {
                Log.d(TAG, " apply : " + throwable.getMessage());
                return Observable.just("new Observable");
            }
        }).subscribe(new Observer<String>() {
            @Override
            public void onSubscribe(Disposable disposable) {

            }

            @Override
            public void onNext(String s) {
                Log.d(TAG, " onNext : s : " + s);
            }

            @Override
            public void onError(Throwable throwable) {
                Log.d(TAG, " onError : " + throwable.getMessage());
            }

            @Override
            public void onComplete() {
                Log.d(TAG, " onComplete ");
            }
        });
    }

打印结果:

onNext : s : 1
onNext : s : 2
apply : error
onNext : s : new Observable
onComplete

onExceptionResumeNext

指示Observable在遇到异常后继续发出项目(但不是另一种类型的throwable)

android rxjava 调用接口 android rxjava操作符_操作符_03


onExceptionResumeNext和onErrorResumeNext类似,不同的是,onExceptionResumeNext如果onError收到的Throwable不是一个Exception,它会将错误传递给观察者的onError方法,不会使用新的Observable。

举个例子

private void doSomeWork() {
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> observableEmitter) throws Exception {
                observableEmitter.onNext("1");
                observableEmitter.onNext("2");
                observableEmitter.onError(new Throwable("error"));
//                observableEmitter.onError(new Exception("error"));
                observableEmitter.onNext("3");
                observableEmitter.onComplete();

            }
        }).onExceptionResumeNext(Observable.just("new Observable"))
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable disposable) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d(TAG, " onNext : s : " + s);
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        Log.d(TAG, " onError : " + throwable.getMessage());
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, " onComplete ");
                    }
                });
    }

onError发射的是个非Exception的Error,onExceptionResumeNext不会使用新的Observable,所以打印结果

onNext : s : 1
onNext : s : 2
onError : error

如果将上方例子中此段代码按如下更改

//                observableEmitter.onError(new Throwable("error"));
                observableEmitter.onError(new Exception("error"));

onError发射的是个Exception的Error,打印结果

onNext : s : 1
onNext : s : 2
onNext : s : new Observable
onComplete

retry

在遇到错误时应尝试重新订阅源Observable。

android rxjava 调用接口 android rxjava操作符_android rxjava 调用接口_04


retry顾名思义就是重试,遇到Error后让源Observable重新从头发射。

举个例子:

private void doSomeWork() {
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> observableEmitter) throws Exception {
                observableEmitter.onNext("1");
                observableEmitter.onNext("2");
                int random = new Random().nextInt(10);
                Log.d(TAG, " subscribe : random : " + random);
                if (random >= 5)
                    observableEmitter.onError(new Throwable("error"));
                observableEmitter.onNext("3");
                observableEmitter.onComplete();

            }
        }).retry(2)
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable disposable) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d(TAG, " onNext : s : " + s);
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        Log.d(TAG, " onError : " + throwable.getMessage());
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, " onComplete ");
                    }
                });
    }

打印结果

onNext : s : 1
onNext : s : 2
subscribe : random : 9
onNext : s : 1
onNext : s : 2
subscribe : random : 8
onNext : s : 1
onNext : s : 2
subscribe : random : 2
onNext : s : 3
onComplete

retryWhen

android rxjava 调用接口 android rxjava操作符_运算符_05


retryWhen和retry类似, 他的区别根据名字也可以知道,他可以让我们控制当xxx时才重试,retryWhen的参数是个Func,我们可以在里面做逻辑处理,如果需要重试,只需要发射一个正常的项即可触发源Observable重试,否则可以发射Error结束。

举个例子:

private void doSomeWork() {
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> observableEmitter) throws Exception {
                observableEmitter.onNext("1");
                observableEmitter.onNext("2");
                int random = new Random().nextInt(10);
                Log.d(TAG, " subscribe : random : " + random);
                if (random >= 5)
                    observableEmitter.onError(new Exception("error"));
                observableEmitter.onNext("3");
                observableEmitter.onComplete();

            }
        }).retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
            @Override
            public ObservableSource<?> apply(Observable<Throwable> throwableObservable) throws Exception {
                return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
                    @Override
                    public ObservableSource<?> apply(Throwable throwable) throws Exception {
                        if (throwable instanceof Exception)
                            return Observable.just("4");
                        else
                            return Observable.just(throwable);
                    }
                });
            }
        })
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable disposable) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d(TAG, " onNext : s : " + s);
                    }

                    @Override
                    public void onError(Throwable throwable) {
                        Log.d(TAG, " onError : " + throwable.getMessage());
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, " onComplete ");
                    }
                });
    }

打印结果

onNext : s : 1
onNext : s : 2
subscribe : random : 5
onNext : s : 1
onNext : s : 2
subscribe : random : 2
onNext : s : 3
onComplete

日常在处理错误异常的时候,我们可能还需要配合do操作符的方法,在某些合适的节点进行处理。这个以后再说吧。