Rxjava中异常处理


rxjava中的异常处理:


rxjava中的异常处理分为两类:


1.当遇到错误时返回指定的的数据


2.当遇到错误时使用重试机制




Checked异常和Unchecked异常

  • Checked异常必须被显式地捕获或者传递,而unchecked异常则可以不必捕获或抛出。
  • Checked异常继承java.lang.Exception类。Unchecked异常继承自java.lang.RuntimeException类。



Unchecked异常

onError。例如以下代码可以打印出“Error!”

@Test
    public void test() throws Exception {
        Observable
                .just("hellow")
                .map(new Func1<String, String>() {
                    @Override
                    public String call(String s) {
                        throw new RuntimeException("产生异常");
//                        return "test";
                    }
                })
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        System.out.println("onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println("onError " + e.getMessage());
                    }

                    @Override
                    public void onNext(String s) {
                        System.out.println("onNext " + s);
                    }
                });
    }



也有例外的情况,那就是... 那些非常严重的错误,以致于RxJava都不能继续运行了。比如 StackOverflowError,这些异常被认为是致命的,对它们来说,调用 onError毫无意义,并没什么用。你可以用 Exceptions.throwIfFatal来过滤掉这些致命的异常并重新抛出,不发射关于它们的通知。





Checked异常

try-catch


@Test
    public void testCheck() throws Exception {
        Observable
                .just("hellow")
                .map(new Func1<String, String>() {
                    @Override
                    public String call(String s) {
                        try{
                            int i = 100/0;
                        }catch (Throwable e){
                            throw Exceptions.propagate(e);
                        }
                        return "test";
                    }
                })
                .subscribe(new Subscriber<String>() {
                    @Override
                    public void onCompleted() {
                        System.out.println("onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println("onError " + e.getMessage());
                    }

                    @Override
                    public void onNext(String s) {
                        System.out.println("onNext " + s);
                    }
                });
    }

Exceptions.propagate()

只是简单地做了这样一件事:如果异常是Checked异常,那就把它包装成Unchecked异常




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



第一种策略是捕获异常并使用新的Observable来替换出现异常的Observable
方法有
onErrorReturn:返回单个对象
onErrorResumeNext:当抛出Throwable时返回一个新的Observable
onExceptionResumeNext:同onErrorResumeNext但只有抛出Exception时才会触发
@Test
    public void testError() throws Exception {
        Observable
                .create(new Observable.OnSubscribe<Integer>() {
                    @Override
                    public void call(Subscriber<? super Integer> subscriber) {
                        if (!subscriber.isUnsubscribed()) {
                            for (int i = 0; i < 20; i++) {
                                subscriber.onError(new RuntimeException("test error"));
                            }
                        }
                    }
                })
                .onErrorReturn(new Func1<Throwable, Integer>() {
                    @Override
                    public Integer call(Throwable throwable) {
                        return 1;
                    }
                })
                .subscribe(new Subscriber<Integer>() {
                    @Override
                    public void onCompleted() {
                        System.out.println("onCompleted ");
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println("onError " + e.getMessage());
                    }

                    @Override
                    public void onNext(Integer integer) {
                        System.out.println("integer " + integer);
                    }
                });
    }



Retry



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

@Test
    public void testError() throws Exception {
        Observable
                .create(new Observable.OnSubscribe<Integer>() {
                    @Override
                    public void call(Subscriber<? super Integer> subscriber) {
                        if (!subscriber.isUnsubscribed()) {
                            for (int i = 0; i < 20; i++) {
                                if (i == 10)
                                    subscriber.onError(new RuntimeException("test error"));

                                subscriber.onNext(i);
                            }
                        }
                    }
                })
                .retry(new Func2<Integer, Throwable, Boolean>() {
                    @Override
                    public Boolean call(Integer integer, Throwable throwable) {
                        if (throwable instanceof RuntimeException) {
                            return false;
                        }
                        return true;
                    }
                })
                .retry(2)
                .subscribe(new Subscriber<Integer>() {
                    @Override
                    public void onCompleted() {
                        System.out.println("onCompleted ");
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println("onError " + e.getMessage());
                    }

                    @Override
                    public void onNext(Integer integer) {
                        System.out.println("integer " + integer);
                    }
                });
    }



可以看到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



参考:



http://www.jianshu.com/p/916b72778145