转载请标明出处:

http://blog.csdn.net/xmxkf/article/details/51658235

本文出自:【openXu的博客】

目录:

1. Catch

  Catch操作符能够拦截原始Observable的onError通知,不让Observable因为产生错误而终止。相当于java中try/catch操作,不能因为抛异常而导致程序崩溃。 retry操作符默认在trampoline调度器上执行。

    

RxJava将Catch实现为三个不同的操作符:

  • onErrorReturn:onErrorReturn方法返回一个原有Observable行为的新Observable镜像,后者会忽略前者的onError调用,不会将错误传递给观察者,作为替代,它会发发射一个特殊的项并调用观察者的onCompleted方法。

    • Javadoc: onErrorReturn(Func1)

    

  • onErrorResumeNext:让Observable在遇到错误时开始发射第二个Observable的数据序列。 onErrorResumeNext方法返回一个原有Observable行为的新Observable镜像 ,后者会忽略前者的onError调用,不会将错误传递给观察者,作为替代,它会开始发射镜像Observable的数据。

    • Javadoc: onErrorResumeNext(Func1)
    • Javadoc: onErrorResumeNext(Observable)

    

  • onExceptionResumeNext: 让Observable在遇到错误时继续发射后面的数据项。 和onErrorResumeNext类似,onExceptionResumeNext方法返回一个镜像原有Observable行为的新Observable,也使用一个备用的Observable,不同的是,如果onError收到的Throwable不是一个Exception,它会将错误传递给观察者的onError方法,不会使用备用的Observable。

    • Javadoc: onExceptionResumeNext(Observable)

    

示例代码:

  注意:在测试onExceptionResumeNext 的时候,不妨试试onError中发射Throwable的情况,这种情况会将onError通知发送给订阅者,并停止。

/*
 * ①.onErrorReturn:
 * 返回一个原有Observable行为的新Observable镜像,
 * 后者会忽略前者的onError调用,不会将错误传递给观察者,
 * 作为替代,它会发发射一个特殊的项并调用观察者的onCompleted方法
 */
Observable.create(new Observable.OnSubscribe<Integer>() {
    @Override
    public void call(Subscriber<? super Integer> subscriber) {
        for(int i = 0;i < 10; i++){
            if(i>3){
                //会忽略onError调用,不会将错误传递给观察者
                subscriber.onError(new Throwable("i太大了"));
            }
            subscriber.onNext(i);
        }
        subscriber.onCompleted();
    }
}).onErrorReturn(new Func1<Throwable, Integer>() {
    //作为替代,它会发发射一个特殊的项并调用观察者的onCompleted方法。
    @Override
    public Integer call(Throwable throwable) {
        return 10;
    }
}).subscribe(new Subscriber<Integer>() {
    @Override
    public void onCompleted() {
        Log.v(TAG, "①onErrorReturn(Func1)->onCompleted");
    }
    @Override
    public void onError(Throwable e) {
        Log.e(TAG, "①onErrorReturn(Func1)->onError:"+e.getMessage());
    }
    @Override
    public void onNext(Integer integer) {
        Log.v(TAG, "①onErrorReturn(Func1)->onNext:"+integer);
    }
});

/*
 * ②.onErrorResumeNext(Observable):
 * 当原Observable发射onError消息时,会忽略onError消息,不会传递给观察者;
 * 然后它会开始另一个备用的Observable,继续发射数据
 */
Observable.create(new Observable.OnSubscribe<Integer>() {
    @Override
    public void call(Subscriber<? super Integer> subscriber) {
        for(int i = 0;i < 10; i++){
            if(i>3){
                //会忽略onError调用,不会将错误传递给观察者
                subscriber.onError(new Throwable("i太大了"));
            }
            subscriber.onNext(i);
        }
        subscriber.onCompleted();
    }
}).onErrorResumeNext(Observable.create(new Observable.OnSubscribe<Integer>() {

    @Override
    public void call(Subscriber<? super Integer> subscriber) {
        for(int i = 10;i < 13; i++){
            subscriber.onNext(i);
        }
        subscriber.onCompleted();
    }
})).subscribe(new Subscriber<Integer>() {
    @Override
    public void onCompleted() {
        Log.v(TAG, "②onErrorResumeNext(Observable)->onCompleted");
    }
    @Override
    public void onError(Throwable e) {
        Log.e(TAG, "②onErrorResumeNext(Observable)->onError:"+e.getMessage());
    }
    @Override
    public void onNext(Integer integer) {
        Log.v(TAG, "②onErrorResumeNext(Observable)->onNext:"+integer);
    }
});

/*
 * ③.onErrorResumeNext(Func1):
 * 和onErrorResumeNext(Observable)相似,但他能截取到原Observable的onError消息
 */
Observable.create(new Observable.OnSubscribe<Integer>() {
    @Override
    public void call(Subscriber<? super Integer> subscriber) {
        for(int i = 0;i < 10; i++){
            if(i>3){
                //会忽略onError调用,不会将错误传递给观察者
                subscriber.onError(new Throwable("i太大了"));
            }
            subscriber.onNext(i);
        }
        subscriber.onCompleted();
    }
}).onErrorResumeNext(new Func1<Throwable, Observable<? extends Integer>>() {
    @Override
    public Observable<? extends Integer> call(Throwable throwable) {
        //throwable就是原Observable发射的onError消息中的Throwable对象
        Log.e(TAG, "③onErrorResumeNext(Func1)->throwable:"+throwable.getMessage());
        //如果原Observable发射了onError消息,将会开启下面的Observable
        return Observable.create(new Observable.OnSubscribe<Integer>() {
            @Override
            public void call(Subscriber<? super Integer> subscriber) {
                for(int i = 100;i < 103; i++){
                    subscriber.onNext(i);
                }
                subscriber.onCompleted();
            }
        });
    }
}).subscribe(new Subscriber<Integer>() {
    @Override
    public void onCompleted() {
        Log.v(TAG, "③onErrorResumeNext(Func1)->onCompleted");
    }
    @Override
    public void onError(Throwable e) {
        Log.e(TAG, "③onErrorResumeNext(Func1)->onError:"+e.getMessage());
    }
    @Override
    public void onNext(Integer integer) {
        Log.v(TAG, "onErrorResumeNext(Func1)->onNext:"+integer);
    }
});

/*
 * ④.onExceptionResumeNext:
 *    和onErrorResumeNext类似,可以说是onErrorResumeNext的特例,
 *    区别是如果onError收到的Throwable不是一个Exception,它会将错误传递给观察者的onError方法,不会使用备用的Observable。
 */
Observable.create(new Observable.OnSubscribe<Integer>() {
    @Override
    public void call(Subscriber<? super Integer> subscriber) {
        for(int i = 0;i < 10; i++){
            if(i>3){
                //如果不是Exception,错误会传递给观察者,不会开启备用Observable
                //subscriber.onError(new Throwable("i太大了"));
                //如果Exception,不会将错误传递给观察者,并会开启备用Observable
                subscriber.onError(new Exception("i太大了哦哦哦"));
            }
            subscriber.onNext(i);
        }
        subscriber.onCompleted();
    }
}).onExceptionResumeNext(Observable.create(new Observable.OnSubscribe<Integer>() {
    @Override
    public void call(Subscriber<? super Integer> subscriber) {
        for(int i = 10;i < 13; i++){
            subscriber.onNext(i);
        }
        subscriber.onCompleted();
    }
})).subscribe(new Subscriber<Integer>() {
    @Override
    public void onCompleted() {
        Log.v(TAG, "④onExceptionResumeNext(Observable)->onCompleted");
    }
    @Override
    public void onError(Throwable e) {
        Log.e(TAG, "④onExceptionResumeNext(Observable)->onError:"+e.getClass().getSimpleName()+":"+e.getMessage());
    }
    @Override
    public void onNext(Integer integer) {
        Log.v(TAG, "④onExceptionResumeNext(Observable)->onNext:"+integer);
    }
});

输出:

①onErrorReturn(Func1)->onNext:0

①onErrorReturn(Func1)->onNext:1

①onErrorReturn(Func1)->onNext:2

①onErrorReturn(Func1)->onNext:3

①onErrorReturn(Func1)->onNext:10

①onErrorReturn(Func1)->onCompleted

②onErrorResumeNext(Observable)->onNext:0

②onErrorResumeNext(Observable)->onNext:1

②onErrorResumeNext(Observable)->onNext:2

②onErrorResumeNext(Observable)->onNext:3

②onErrorResumeNext(Observable)->onNext:10

②onErrorResumeNext(Observable)->onNext:11

②onErrorResumeNext(Observable)->onNext:12

②onErrorResumeNext(Observable)->onCompleted

③onErrorResumeNext(Func1)->onNext:0

③onErrorResumeNext(Func1)->onNext:1

③onErrorResumeNext(Func1)->onNext:2

③onErrorResumeNext(Func1)->onNext:3

③onErrorResumeNext(Func1)->throwable:i太大了

③onErrorResumeNext(Func1)->onNext:100

③onErrorResumeNext(Func1)->onNext:101

③onErrorResumeNext(Func1)->onNext:102

③onErrorResumeNext(Func1)->onCompleted

④onExceptionResumeNext(Observable)->onNext:0

④onExceptionResumeNext(Observable)->onNext:1

④onExceptionResumeNext(Observable)->onNext:2

④onExceptionResumeNext(Observable)->onNext:3

④onExceptionResumeNext(Observable)->onNext:10

④onExceptionResumeNext(Observable)->onNext:11

④onExceptionResumeNext(Observable)->onNext:12

④onExceptionResumeNext(Observable)->onCompleted

2. Retry

  顾名思义,retry的意思就是试着重来,当原始Observable发射onError通知时,retry操作符不会让onError通知传递给观察者,它会重新订阅这个Observable一次或者多次(意味着重新从头发射数据),所以可能造成数据项重复发送的情况。

  如果重新订阅了指定的次数还是发射了onError通知,将不再尝试重新订阅,它会把最新的一个onError通知传递给观察者。

    

RxJava中将Retry操作符的实现为retry和retryWhen两种:

  • retry:

    • Javadoc: retry():无论收到多少次onError通知,都会继续订阅并重发原始Observable,直到onCompleted。

    • Javadoc: retry(long):接受count参数的retry会最多重新订阅count次,如果次数超过了就不会尝试再次订阅,它会把最新的一个onError通知传递给他的观察者。

    • Javadoc: retry(Func2): 这个版本的retry接受一个谓词函数作为参数,这个函数的两个参数是:重试次数和导致发射onError通知的Throwable。这个函数返回一个布尔值,如果返回true,retry应该再次订阅和镜像原始的Observable,如果返回false,retry会将最新的一个onError通知传递给它的观察者。

示例代码:

/**
 * ①. retry()
 *     无限次尝试重新订阅
 */
Observable.create(new Observable.OnSubscribe<Integer>() {
    @Override
    public void call(Subscriber<? super Integer> subscriber) {
        for(int i = 0; i<3; i++){
            if(i==1){
                Log.v(TAG, "①retry()->onError");
                subscriber.onError(new RuntimeException("always fails"));
            }else{
                subscriber.onNext(i);
            }
        }
    }
}).retry()    //无限次尝试重新订阅
.subscribe(new Subscriber<Integer>() {
    @Override
    public void onCompleted() {
        Log.v(TAG, "①retry()->onCompleted");
    }
    @Override
    public void onError(Throwable e) {
        Log.v(TAG, "①retry()->onError"+e.getMessage());
    }
    @Override
    public void onNext(Integer i) {
        Log.v(TAG, "①retry()->onNext"+i);
    }
});

/**
 * ②. retry(count)
 *     最多2次尝试重新订阅
 */
Observable.create(new Observable.OnSubscribe<Integer>() {
    @Override
    public void call(Subscriber<? super Integer> subscriber) {
        for(int i = 0; i<3; i++){
            if(i==1){
                Log.v(TAG, "②retry(count)->onError");
                subscriber.onError(new RuntimeException("always fails"));
            }else{
                subscriber.onNext(i);
            }
        }
    }
}).retry(2)    //最多尝试2次重新订阅
        .subscribe(new Subscriber<Integer>() {
            @Override
            public void onCompleted() {
                Log.v(TAG, "②retry(count)->onCompleted");
            }
            @Override
            public void onError(Throwable e) {
                Log.v(TAG, "②retry(count)->onError"+e.getMessage());
            }
            @Override
            public void onNext(Integer i) {
                Log.v(TAG, "②retry(count)->onNext"+i);
            }
        });

/**
 * ③. retry(Func2)
 */
Observable.create(new Observable.OnSubscribe<Integer>() {
    @Override
    public void call(Subscriber<? super Integer> subscriber) {
        for(int i = 0; i<3; i++){
            if(i==1){
                Log.v(TAG, "③retry(Func2)->onError");
                subscriber.onError(new RuntimeException("always fails"));
            }else{
                subscriber.onNext(i);
            }
        }
    }
}).retry(new Func2<Integer, Throwable, Boolean>() {
    @Override
    public Boolean call(Integer integer, Throwable throwable) {
        Log.v(TAG, "③发生错误了:"+throwable.getMessage()+",第"+integer+"次重新订阅");
        if(integer>2){
            return false;//不再重新订阅
        }
        //此处也可以通过判断throwable来控制不同的错误不同处理
        return true;
    }
}).subscribe(new Subscriber<Integer>() {
    @Override
    public void onCompleted() {
        Log.v(TAG, "③retry(Func2)->onCompleted");
    }
    @Override
    public void onError(Throwable e) {
        Log.v(TAG, "③retry(Func2)->onError"+e.getMessage());
    }
    @Override
    public void onNext(Integer i) {
        Log.v(TAG, "③retry(Func2)->onNext"+i);
    }
});

输出:

①retry()->onNext0

①retry()->onError

①retry()->onNext0

①retry()->onError

…无限次

②retry(count)->onNext0

②retry(count)->onError

②retry(count)->onNext0

②retry(count)->onError

②retry(count)->onNext0

②retry(count)->onError

②retry(count)->onErroralways fails

③retry(Func2)->onNext0

③retry(Func2)->onError

③发生错误了:always fails,第1次重新订阅

③retry(Func2)->onNext0

③retry(Func2)->onError

③发生错误了:always fails,第2次重新订阅

③retry(Func2)->onNext0

③retry(Func2)->onError

③发生错误了:always fails,第3次重新订阅

③retry(Func2)->onErroralways fails

  • retryWhen:

      retryWhen和retry类似,区别是,retryWhen将onError中的Throwable传递给一个函数,这个函数产生另一个Observable,retryWhen观察它的结果再决定是不是要重新订阅原始的Observable。如果这个Observable发射了一项数据,它就重新订阅,如果这个Observable发射的是onError通知,它就将这个通知传递给观察者然后终止。

示例代码:

Observable.create((Subscriber<? super String> s) -> {
    System.out.println("subscribing");
    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);

输出:

subscribing

delay retry by 1 second(s)

subscribing

delay retry by 2 second(s)

subscribing

delay retry by 3 second(s)

subscribing

有问题请留言,有帮助请点赞(^__^)

源码下载:

https://github.com/openXu/RxJavaTest

RxJava操作符(06-错误处理)的更多相关文章

  1. RxJava 操作符 on和doOn 线程切换 调度 Schedulers 线程池 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  2. RxJava操作符总结之过滤

    RxJava操作符总结之过滤 jsut() just(T t1, T t2, T t3 ....) ,just能够传入多个同样类型的參数,并将当前參数一个接着一个的发送. Observable.jus ...

  3. RxJava操作符实践:8_算术和聚合操作之3_min

    发射原始Observable的最小值. Min操作符操作一个发射数值的Observable并发射单个值:最小的那个值. RxJava中,min属于rxjava-math模块. min接受一个可选参数, ...

  4. RxJava(六) retryWhen操作符实现错误重试机制

    欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/51539708 本文出自:[余志强的博客] 业务需求 当我们在app里 ...

  5. RxJava操作符(07-辅助操作)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51658445 本文出自:[openXu的博客] 目录: Delay Do Materiali ...

  6. RxJava操作符(04-过滤操作)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51656494 本文出自:[openXu的博客] 目录: Debounce Distinct ...

  7. RxJava操作符(02-创建操作)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51645348 本文出自:[openXu的博客] 目录: Create Defer Empty ...

  8. Rxjava - 操作符,线程操作的简单使用

    目录 创建操作符 10种常用的操作符定义 下面做几个操作符的demo演示 create from repeat defer interval Scheduler 什么是Scheduler? 如何使用S ...

  9. [RxJava]在学习RxJava中的错误理解

    关于RxJava语法的问题与理解   最近看到一个blog-RxJava 写到关于Observable数据异步加载的介绍.针对fromCallable和just操作符在使用上的问题来跟大家针对代码进行 ...

随机推荐

  1. Angular1.x使用小结

    之前工作以Angular1.x为主,主要做业务系统,以后工作中技术栈可能以vue为主,在此对Angular1.x的使用做一个简单总结,这里使用1.5+版本. 基本概念 1.依赖注入 依赖注入,在ang ...

  2. php中一些提高性能的技巧

    php中一些提高性能的技巧 tags:php性能 提高性能 php中的@ php的静态 引言:php作为一种脚本语言,本身的性能上肯定是不如c++或者java的.拥有简单易学的特性的同时,性能提升的空 ...

  3. python selenum 爬取淘宝

    # -*- coding:utf-8 -*- # author : yesehngbao # time:2018/3/29 import re import pymongo from lxml imp ...

  4. 利用 Scrapy 爬取知乎用户信息

    思路:通过获取知乎某个大V的关注列表和被关注列表,查看该大V和其关注用户和被关注用户的详细信息,然后通过层层递归调用,实现获取关注用户和被关注用户的关注列表和被关注列表,最终实现获取大量用户信息. 一 ...

  5. [TJOI2017]异或和

    题目描述 在加里敦中学的小明最近爱上了数学竞赛,很多数学竞赛的题都是与序列的连续和相关的.所以对于一个序列,求出它们所有的连续和来说,小明觉得十分的 简单.但今天小明遇到了一个序列和的难题,这个题目不 ...

  6. 计蒜客NOIP模拟赛(2) D1T2 表演艺术

    凡和邻家男孩玩完了纸牌,兴致很高,于是准备了一场表演艺术对抗赛. 他特意请来了很多表演艺术家,分成绿黑两队,进行名为 PK,实则捞金的表演. 凡为了捞金,开设了一个赌局,在比赛开始之前招揽人们来押注谁 ...

  7. java集合之LinkedList源码解读

    源自:jdk1.8.0_121 LinkedList继承自AbstractSequentialList,实现了List.Deque.Cloneable.Serializable. LinkedList ...

  8. 阿里技术一面,Java研发岗

    之前过了个简单的简历面,过了几天后没打来以为凉了,然后昨晚又接到了电话,括号内容是回答说的,理解有限,不一定都对,欢迎纠正-加油每一个牛友们! 阿里一面: 1.学过哪些技术知识呢? 2.说说接口和抽象 ...

  9. Java的五子棋实现

    Java 五子棋 注:除机器人算法外其余借鉴于MLDN. package MyFiveChess; import robot.*; import java.awt.*; import javax.sw ...

  10. SSM框架原理,作用及使用方法(非原创)

    原帖:地址https://blog.csdn.net/bieleyang/article/details/77862042 如有侵权请联系删除 作用: SSM框架是spring MVC ,spring ...