异常处理

在Rxjava订阅的Observable有时会抛出异常,在RxJava中有两大类策略,一个是准备备用的Observable,在发生异常时将subscriber订阅到新的Observable上,第二种是重试。

catch

第一种策略是捕获异常并使用新的Observable来替换出现异常的Observable
方法有
onErrorReturn:返回单个对象
onErrorResumeNext:当抛出Throwable时返回一个新的Observable
onExceptionResumeNext:同onErrorResumeNext但只有抛出Exception时才会触发

@Test
public void onException() {
    Observable<Object> obs = Observable
            .create(sub -> {
                for (int i = 0; i < 10; i++) {
                    if (i == 1) {
						//抛出异常
                        sub.onError(new RuntimeException("error"));
                    }
                    sub.onNext(i);
                }
            });
    obs.onExceptionResumeNext(Observable.just("new resumed observable"))
            .subscribe(obj -> System.out.println(obj));
}
-------输出---------
0
new resumed observable

从输出中看出当遇到异常后会调用注册的备用Observable

Retry

该策略当遇到exception时会进行重试
有两类方法
retry:可以根据重试次数和错误原因来判断是否需要重试

@Test
public void retry() {
    Observable<Object> obs = Observable
            .create(sub -> {
                for (int i = 0; i < 10; i++) {
                    if (i == 1) {
                        sub.onError(new RuntimeException("error"));
                    }
                    sub.onNext(i);
                }
            });
    obs.retry((time,ex)->{
        if(time==2 && ex instanceof RuntimeException){
            return false;
        }
        return true;
    })
      .subscribe(obj -> System.out.println(obj));
}
-------输出---------
0
0

rx.exceptions.OnErrorNotImplementedException: error

可以看到retry中判断次数和错误类型根据返回决定是否要重试
retryWhen:通过将异常组成Observable并通过返回的Observable的结果来判断是否重试
下面是官方的例子,第一次会1秒重试,第二次等待2秒,第三次等待3秒,第四次停止重试

@Test
public void retryWhen(){
    Observable.create((s) -> {
        s.onNext("subcribe");
        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);
}
-------输出---------
subcribe
delay retry by 1 second(s)
subcribe
delay retry by 2 second(s)
subcribe
delay retry by 3 second(s)
subcribe