RxJava——操作符篇

一、RxJava操作符概述

  • RxJava中的操作符就是为了提供函数式的特性,函数式最大的好处就是使得数据处理简洁易懂。
    操作符实质上就是RxJava函数式编程模式的体现,在上篇文章中,我详细阐述了RxJava中观察者模式、Iterator模式、函数式编程模式概念的解读,详情请戳→文章传送门 。

Rxjava操作符的类型众多,在本文中,我详细解释如图1.1所示的9种操作符。

RxJava——操作符篇_第1张图片
图1.1 RxJava操作符的分类
本项目案例代码已上传Github,详情戳→ GitHub案例代码。
图1.2 RxJava操作符案例图

二、RxJava操作符详解

1、创建操作符

创建操作符的分类如下图所示,关于create操作符的详细操作可在我的上篇文章中查看,在本文中不加以赘述,文章链接戳→文章传送门 。在本文中从from操作符开始介绍。

RxJava——操作符篇_第2张图片
图2.1 创建操作符的分类

  • :在这里,我将请求的不完整回调在父类中进行了封装,具体代码可查看GitHub的代码链接。

①from操作符

在这里以发送数组为例,from操作符的使用代码如下所示:

        //from操作符,创建以数组内容发送事件的Observable
        String[] observableArr = new String[]{"Alex", "Payne"};
        //onNextAction、onErrorAction提取到父类中,具体代码可查看GitHub的代码链接
        Observable.from(observableArr).subscribe(onNextAction, onErrorAction);

首先,我们查看如下所示from操作符的结构图,可以看到它有多种实现方式,但是有一个共同点,都会返回一个Observable对象。

RxJava——操作符篇_第3张图片
图2.1.1 from操作符操作结构图
实质上,Observable将数组中的元素逐个进行发送,在发送过程中转换为Observable对象。
进一步查看源码,可得知from操作符的作用: 将一个Iterable、一个Future、 或者一个数组,内部通过代理的方式转换成一个Observable。
Future转换为OnSubscribe是通过OnSubscribeToObservableFuture进行的,Iterable转换通过OnSubscribeFromIterable进行。数组通过OnSubscribeFromArray转换。

②just操作符

使用代码如下所示:

        //just操作符,创建将逐个内容进行发送的Observable,其内部发送内容在内部以from的操作符的方式进行转换
        Observable.just("Alex", "Payne").subscribe(onNextAction);
RxJava——操作符篇_第4张图片
图2.1.2 just操作符结构图

查看just操作符的结构图,结合源码得知,just操作符将单个参数发送的内容通过ScalarSynchronousObservable转换为一个新的Observable对象,而将多个参数发送的内容转换为一个数组,然后将数组通过from操作符进行发送。

③interval操作符

interval操作符使用代码如下所示:

        //interval操作符,创建以1秒为事件间隔发送整数序列的Observable
        Observable.interval(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread()).subscribe(onNextAction);
图2.1.3 interval操作符结构图

查看interval的结构图,其只能发送Long类型的数,实质上其作用为:创建一个按固定时间间隔发射整数序列的Observable,这个序列为一个无限递增的整数序列。
需要注意的是:interval默认在computation调度器上执行。你也可以传递一个可选的Scheduler参数来指定调度器。

④range操作符

range操作符使用的代码如下所示:

        //range操作符,创建以发送范围内的整数序列的Observable
        Observable.range(0, 3).subscribe(onNextAction);

range操作符发射一个范围内的有序整数序列,并且我们可以指定范围的起始和长度
RxJava——操作符篇_第5张图片
图2.1.4 range操作符参数释义

⑤repeat操作符

repeat操作符使用的代码如下所示:

        //repeat操作符,创建一个以N次重复发送数据的Observable
        Observable.range(0, 3).repeat(2).subscribe(onNextAction);

在这里需要强调一下,它不是创建一个Observable,而是重复发射原始Observable的数据序列,这个序列或者是无限的,或者通过repeat(n)指定重复次数。

2、变换操作符

在这里我介绍如下图所示7种变换操作符,变换操作符的作用是将源Observable发送的数据进行变换。
RxJava——操作符篇_第6张图片
图2.1 变换操作符的分类

①map操作符

map操作符使用的代码如下所示:

         //map操作符,通过指定一个Func,将Observable转换为另一个Observable对象并发送
         Observable.just("Alex_Payne")
                   .map(new Func1() {
                       @Override
                       public String call(String s) {
                           return "My Name is" + s;
                       }
                   }).subscribe(onNextAction);

map操作符将源Observable发送的数据转换为一个新的Observable对象。
在这里,Func1和Action的区别在于,Func1包装的是有返回值的方法。另外,和ActionX 一样,FuncX 也有多个,用于不同参数个数的方法。
FuncX 和 ActionX 的区别在 FuncX 包装的是有返回值的方法。

②flatMap操作符

flatMap操作符使用的代码如下所示:

        //flatMap操作符,将Observable发送的数据集合转换为Observable集合
        //flatMap的合并运行允许交叉,允许交错的发送事件
        String[] observableArr = {"Alex", "Max", "Bruce", "Frank", "Tom"};
        Observable.from(observableArr).flatMap(new Func1>() {
              @Override
              public Observable call(String s) {
                 return Observable.just("My Name is:" + s);
              }
         }).subscribe(onNextAction);

源Observable通过flatMap操作符转换为包含源Observable发送的所有子条目的Observable集合,可见下图的示意图,然后从Observable集合中逐个取出转化为单个Observable对象进行发送。不同于map操作符的一点就是一对多的转化。

RxJava——操作符篇_第7张图片
图2.2.2 flatMap转换示意图
它的应用场景可以体现在源Observable发送的内容为一个复杂的数据集,例如一个Bean对象,而该外层Bean对象中一个成员变量为另一个内层Bean对象,我们想要拆解外层Bean对象获取内层Bean对象,就可以用flatMap操作符。
注意:FlatMap对这些Observables发射的数据做的是合并(merge)操作,因此它们可能是交错的。

③concatMap操作符

concatMap操作符使用的代码如下所示:

        //concatMap操作符,将Observable发送的数据集合转换为Observable集合
        //解决了flatMap的交叉问题,将发送的数据连接发送
        String[] observableArr = {"Alex", "Max", "Bruce", "Frank", "Tom"};
        Observable.from(observableArr).concatMap(new Func1>() {
              @Override
              public Observable call(String s) {
                 return Observable.just("My Name is:" + s);
              }
         }).subscribe(onNextAction);

concatMap操作符类似于flatMap操作符,不同的一点是它按次序连接。

④cast操作符

cast操作符使用的代码如下所示:

         //cast操作符,将类对象进行转换
         Object[] objectsArr = {"1", "2", "3"};
         Observable.from(objectsArr).cast(String.class).subscribe(onNextAction);

cast操作符将源Observable发送的数据都强制转换为一个指定的类型,然后再发射数据。
需强调的一点是只能由父类对象转换为子类对象,否则会报错。

⑤flatMapIterable操作符

flatMapIterable操作符使用的代码如下所示:

         //将数据集合转换为Iterable,在Iterable中对数据进行处理
         Observable.just(1, 2, 3).flatMapIterable(new Func1>() {
             @Override
             public Iterable call(Integer number) {
                   ArrayList mList = new ArrayList<>();
                   mList.add(1000 + number);
                   return mList;
               }
          }).subscribe(onNextAction);

flatMapIterable相当于是flatMap的变体,直接在内部以Iterable接口将集合数据进行接收,示意图如下所示:


RxJava——操作符篇_第8张图片
图2.2.5 flatMapIterable示意图

⑥buffer操作符

buffer操作符使用的代码如下所示:

           //buffer操作符,将原有Observable转换为一个新的Observable,这个新的Observable每次发送一组值,而不是一个个进行发送
           Observable.just(1, 2, 3, 4, 5, 6)
              .buffer(3).subscribe(new Action1>() {
              @Override
              public void call(List mList) {
                   for (Integer i : mList) {
                        Toast.makeText(getActivity(), "new Number i is:" + i, Toast.LENGTH_SHORT).show();
                   }
                   Toast.makeText(getActivity(), "Another request is called", Toast.LENGTH_SHORT).show();
                 }
             });

buffer操作符将原有Observable转换为一个新的Observable,这个新的Observable每次发送一组值,而不是一个个进行发送,我们可以定义这个新的Observable存放几个原有的Observable对象。


RxJava——操作符篇_第9张图片
图2.2.6 buffer操作符示意图

⑦groupBy操作符

groupBy操作符使用的代码如下所示:

           //groupBy操作符,可以做分组操作
           Observable.range(0, 10).groupBy(new Func1() {
               @Override
               public Integer call(Integer num) {
                  return num % 3;
                  }
             }).subscribe(new Action1>() {
               @Override
               public void call(final GroupedObservable groupedObservable) {
                  groupedObservable.subscribe(new Action1() {
                    @Override
                    public void call(Integer num) {
                          Toast.makeText(getActivity(), "当前的组别是:" + groupedObservable.getKey() + "组别内的数字是:" + num, Toast.LENGTH_SHORT).show();
                        }
                   });
               }
           });

groupBy操作符,将原有的Observable对象转换为发送一组Observable集合的GroupedObservable对象,可以做分组操作,GroupedObservable将分组完毕的Observable对象可以继续发送。
注意:groupBy将原始Observable分解为一个发射多个GroupedObservable的Observable,一旦有订阅,每个GroupedObservable就开始缓存数据。因此,如果你忽略这些GroupedObservable中的任何一个,这个缓存可能形成一个潜在的 内存泄露 。因此,如果你不想观察,也不要忽略GroupedObservable。你应该使用像take(0)这样会丢弃自己的缓存的操作符。

3、过滤操作符

过滤操作符用于从Observable发射的数据中进行选择,在这里介绍如下图所示的8种。
RxJava——操作符篇_第10张图片
图3.1 过滤操作符的分类

①filter操作符

filter操作符使用的代码如下所示:

           //filter过滤操作符,对Observable发送的内容根据自定义的规则进行过滤
           Observable.range(0, 5).filter(new Func1() {
             @Override
             public Boolean call(Integer num) {
                      return num > 2;//自定义的条件,只有符合条件的结果才会提交给观察者
             }
           }).subscribe(onNextAction);

filter默认不在任何特定的调度器上执行。

②elementAt操作符

elementAt操作符使用的代码如下所示:

            //elementAt操作符,用于返回指定位置后一位的数据,即脚标+1的数据
           //在这里发送0、1、2、3、4,脚标为3的数据为2,发送其后一位数据3
           Observable.range(0, 5).elementAt(3).subscribe(onNextAction);

elementAt操作符获取原始Observable发射的数据序列指定索引位置的数据项,然后当做自己的唯一数据发射。对应示意图如下:
RxJava——操作符篇_第11张图片
图2.3.2 elementAt操作符示意图

③distinct操作符

distinct操作符使用的代码如下所示:

           //distinct操作符,用于Observable发送的元素的去重
           Observable.just(1, 1, 2, 2, 2, 3).distinct().subscribe(onNextAction);

在这里需要强调一点:distinct操作符只允许还没有发射过的数据项通过。

④skip操作符

skip操作符使用的代码如下所示:

           //skip操作符,用于Observable发送的元素前N项去除掉
           Observable.range(0, 5).skip(2).subscribe(onNextAction);

skip操作符抑制Observable发射的前N项数据,只发送后N项数据
RxJava——操作符篇_第12张图片
图2.3.4 skip操作符示意图

⑤take操作符

            //take操作符,用于Observable发送的元素只取前N项
            Observable.range(0, 5).take(2).subscribe(onNextAction);
RxJava——操作符篇_第13张图片
图2.3.5 take操作符示意图

⑥ignoreElements操作符

            //ignoreElements操作符,忽略掉源Observable发送的结果,只把Observable的onCompleted或onError发送
            Observable.range(0, 5).ignoreElements().subscribe(onNextAction, onErrorAction, onCompletedAction);

IgnoreElements操作符抑制原始Observable发射的所有数据,只允许它的终止通知(onError或onCompleted)进行发送。

⑦throttleFirst操作符

            //throttleFirst操作符,会定期发送这个时间段里源Observable发送的第一个数据
            //throttleFirst操作符默认在computaioin调度器上执行,其他的数据都会被过滤掉
             Observable.create(new Observable.OnSubscribe() {
                    @Override
                    public void call(Subscriber subscriber) {
                         for (int i = 0; i < 10; i++) {
                             subscriber.onNext(i);
                             //线程休眠100毫秒
                             try {
                                  Thread.sleep(100);
                             } catch (InterruptedException e) {
                             e.printStackTrace();
                             }
                         }
                   }
           })
           .throttleFirst(200, TimeUnit.MILLISECONDS)
           .subscribe(onNextAction);

throttleFirst操作符会按照固定的时间间隔将信息进行发送。在这里我设置的事件间隔为200毫秒,其中每发送一个数据线程休眠100毫秒,所以最后会显示的数据为0,示意图如下:
RxJava——操作符篇_第14张图片
图2..3.7 throttleFirst操作符示意图

注:throttleFirst操作符默认在computation调度器上执行,但是你可以使用第三个参数指定其它的调度器。

⑧throttleWithTimeOut操作符

                 //throttleWithTimeout操作符
                 //源发射数据时,如果两次数据的发射间隔小于指定时间,就会丢弃前一次的数据,直到指定时间内都没有新数据发射时才进行发射           
                 Observable.create(new Observable.OnSubscribe() {
                 @Override
                  public void call(Subscriber subscriber) {
                         subscriber.onNext(1);
                         try {
                              Thread.sleep(500);
                          } catch (InterruptedException e) {
                              throw Exceptions.propagate(e);
                          }
                         subscriber.onNext(2);
                         try {
                              Thread.sleep(500);
                          } catch (InterruptedException e) {
                              throw Exceptions.propagate(e);
                          }
                          subscriber.onNext(3);
                          try {
                             Thread.sleep(1000);
                           } catch (InterruptedException e) {
                               throw Exceptions.propagate(e);
                           }
                          subscriber.onNext(4);
                          subscriber.onNext(5);
                          subscriber.onCompleted();
                      }
                })
                .throttleWithTimeout(800, TimeUnit.MILLISECONDS)
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(onNextAction);

在这里,我设置的时间间隔指定为800毫秒,所以最后显示的数据是有3、4、5。

4、组合操作符

组合操作符用于将多个Observable组合成一个单一的Observable,在这里我介绍如下图所示5种操作符:


RxJava——操作符篇_第15张图片
图4.1 组合操作符分类

①startWith组合操作符

startWith组合操作符使用的代码如下所示:

                 //startWith操作符,会在发送的数据之前插入数据
                 Observable.range(3, 5).startWith(0, 10086).subscribe(onNextAction);

很简单,会在发送的数据序列前插入数据序列,并且会发送插入的数据序列。

②merge组合操作符

merge组合操作符使用的代码如下所示:

                 //merge操作符,会将多个Observable对象合并到一个Observable对象中进行发送
                 Observable firstObservable = Observable.just(0, 1, 2).subscribeOn(Schedulers.io());
                 Observable secondObservable = Observable.just(3, 4, 5);
                 Observable.merge(firstObservable, secondObservable).subscribe(onNextAction, onErrorAction);

如下图所示,merge操作符会将多个Observable对象进行合并。

RxJava——操作符篇_第16张图片
图2.4.2 merge操作符示意图
需要注意的是:merge可能会让合并的Observables发射的数据交错。
在这里我将firstObservable指定在IO线程中进行发送,secondObservable没有指定线程,两者合并然后发送数据时便会产生数据交错的现象。

③concat组合操作符

concat组合操作符使用的代码如下所示:

                 //concat操作符,会将多个Observable对象合并到一个Observable对象中进行发送,严格按照顺序进行发送
                 Observable firstObservable = Observable.just(0, 1, 2).subscribeOn(Schedulers.io());
                 Observable secondObservable = Observable.just(3, 4, 5);
                 Observable.concat(firstObservable, secondObservable)
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(onNextAction);

concat操作符不同于merge操作符的区别就是:会将多个Observable对象合并到一个Observable对象中进行发送,严格按照顺序进行发送。如下图所示,直到第一个Observable发送完毕数据后,第二个Observable才会进行数据的发送。

RxJava——操作符篇_第17张图片
图2.4.3 concat组合操作符

④zip组合操作符

zip组合操作符使用的代码如下所示:

                 //zip操作符,会将多个Observable对象转换成一个Observable对象然后进行发送,转换关系可根据需求自定义
                 Observable integerObservable = Observable.range(0, 4);
                 Observable stringObservable = Observable.just("a", "b", "c", "d");
                 Observable.zip(integerObservable, stringObservable, new Func2() {
                    @Override
                    public String call(Integer num, String info) {
                        //在这里的转换关系为将数字与字串内容进行拼接
                        return "数字为:" + num + "……字符为:" + info;
                    }
                }).subscribe(onNextAction);

RxJava——操作符篇_第18张图片
image.png

zip操作符返回一个Obversable,它使用这个函数按顺序结合两个或多个Observables发射的数据项,然后它发射这个函数返回的结果。
它按照严格的顺序进行数据发送。它只发射与发射数据项最少的那个Observable一样多的数据。

⑤combineLastest组合操作符

combineLastest组合操作符使用的代码如下所示:

                //combineLastest操作符,会将多个Observable对象转换一个Observable对象然后进行发送,转换关系可以根据需求自定义
                //不同于zip操作符的是,会将最新发送的数据组合到一起
                integerObservable = Observable.just(1, 2, 3);
                stringObservable = Observable.just("a", "b", "c");
                Observable.combineLatest(integerObservable, stringObservable, new Func2() {
                    @Override
                    public String call(Integer num, String info) {
                        //在这里的转换关系为将数字与字串内容进行拼接
                        return "数字为:" + num + "……字符为:" + info;
                    }
                }).subscribe(onNextAction);

当两个Observables中的任何一个发射了数据时,使用一个函数结合每个Observable发射的最近数据项,并且基于这个函数的结果发射数据。可在本案例代码中进行验证。

5、辅助操作符

辅助操作符就是处理Observable的帮助动作,在这里介绍如下5种辅助操作符。
RxJava——操作符篇_第19张图片
图2.5 辅助操作符分类

①delay操作符

delay操作符使用的代码如下所示:

                //delay操作符可以让源Observable对象发送数据之前暂停一段制定的时间
                Observable.just(1, 2, 3)
                          .delay(2, TimeUnit.SECONDS)
                          .observeOn(AndroidSchedulers.mainThread())
                          .subscribe(onNextAction);

在这里我将延时时间设置为2秒,延迟指定的时间后发射源Observable中的数据。

②do操作符

do操作符使用的代码如下所示:

                //doOnNext是do操作符中的一种
                Observable.range(0, 3).doOnNext(onNextAction).subscribe(onNextAction);

do操作符,其下细分有很多内容,以doOnNext为例,其作用就是为源Observable对象发送数据后,当Subscriber接收到数据时,即当Subscriber的onNext方法被调用时,提供回调相应数据。

③subscribeOn辅助操作符

④observeOn辅助操作符

subscribeOn、observeOn操作符使用的代码如下所示:

                 Observable.just("当前的线程ID为" + Thread.currentThread().getName())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(onNextAction);       
  • subscribeOn操作符,指定subscribe()所发生的线程,即Observable.OnSubscribe被激活时所处的线程。或者叫做事件产生的线程。
  • observeOn操作符,指定Subscriber所运行的线程。或者叫做事件消费的线程。

上篇文章中我提到Schedulers可以使得RxJava实现线程切换,实质上就是借助于lift变换方法进行转换,subscribeOn发生在下图的通知过程,observeOn发生在下图中的发送过程。

RxJava——操作符篇_第20张图片
图2.5.4 Observable与Subscriber的转换关系图

⑤timeout辅助操作符

timeout操作符使用的代码如下所示:

                //timeout操作符,如果源Observable对象过了一段时间没有发送数据,timeout会以onError通知终止这个Observable
                Observable.create(new Observable.OnSubscribe() {
                    @Override
                    public void call(Subscriber subscriber) {
                        for (int i = 0; i < 5; i++) {
                            try {
                                Thread.sleep(i * 100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            subscriber.onNext(i);
                        }
                    }
                }).timeout(200, TimeUnit.MILLISECONDS, Observable.just(100, 200))
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(onNextAction);

需要强调的一点是,在这里timeout(long timeout, TimeUnit timeUnit, Observable other)是timeout其中的一种,它在超时的时候会将源Observable转换为备用的Observable对象进行发送。

6、错误操作符

RxJava——操作符篇_第21张图片
图2.6 错误操作符的分类

①catch操作符

实质上在这里catch操作符细分有三种实现方案:onErrorReturn、onErrorResumeNext、onExceptionResumeNext。

  • 首先分析onErrorReturn的代码:
                Observable.create(new Observable.OnSubscribe() {
                    @Override
                    public void call(Subscriber subscriber) {
                        for (int i = 0; i < 5; i++) {
                            if (i > 3) {
                                subscriber.onError(new Throwable("User Alex Defined Error"));
                            }
                            subscriber.onNext(i);
                        }
                    }
                }).onErrorReturn(new Func1() {
                    @Override
                    public Integer call(Throwable throwable) {
                        return 404;
                    }
                }).subscribe(onNextAction, onErrorAction, onCompletedAction);

onErrorReturn操作符,会在遇到错误时,停止源Observable的,并调用用户自定义的返回请求,实质上就是调用一次OnNext方法进行内容发送后,停止消息发送。

  • 然后分析onErrorResumeNext的代码:
                Observable.create(new Observable.OnSubscribe() {
                    @Override
                    public void call(Subscriber subscriber) {
                        for (int i = 0; i < 5; i++) {
                            if (i > 3) {
                                subscriber.onError(new Throwable("User Alex Defined Error"));
                            }
                            subscriber.onNext(i);
                        }
                    }
                }).onErrorResumeNext(new Func1>() {
                    @Override
                    public Observable call(Throwable throwable) {
                        return Observable.just(100,101,102);
                    }
                }).subscribe(onNextAction,onErrorAction,onCompletedAction);

onErrorResumeNext操作符,会在源Observable遇到错误时,立即停止源Observable的数据发送,并取用新的Observable对象进行新的数据发送。

  • 最后,分析onExceptionResumeNext的代码:
                Observable.create(new Observable.OnSubscribe() {
                    @Override
                    public void call(Subscriber subscriber) {
                        for (int i = 0; i < 5; i++) {
                            if (i > 3) {
                                subscriber.onError(new Throwable("User Alex Defined Error"));
                            }
                            subscriber.onNext(i);
                        }
                    }
                }).onExceptionResumeNext(Observable.just(100,101,102)).subscribe(onNextAction,onErrorAction,onCompletedAction);

onExceptionResumeNext,会将错误发给Observer,而不会调用备用的Observable

②retry操作符

retry操作符实现的代码如下所示:

                //retry操作符,当遇到exception时会进行重试,重试次数可以由用户进行定义
                Observable.create(new Observable.OnSubscribe() {
                    @Override
                    public void call(Subscriber subscriber) {
                        for (int i = 0; i < 5; i++) {
                            if (i > 1) {
                                subscriber.onError(new Throwable("User Alex Defined Error"));
                            }
                            subscriber.onNext(i);
                        }
                    }
                }).retry(2).subscribe(onNextAction,onErrorAction,onCompletedAction);

retry操作符不会将原始Observable的onError通知传递给观察者,它会重新订阅这个Observable。


RxJava——操作符篇_第22张图片
图2.6.2 retry操作符示意图

7、布尔操作符

布尔操作符根据给定规则进行判断,是否符合规则然后返回布尔值。布尔操作符意义简单操作简便在这里介绍如下5种:


RxJava——操作符篇_第23张图片
图2.7 布尔操作符分类

①all操作符

all操作符实现的代码如下所示:

                Observable.just(1, 2, 3, 4).all(new Func1() {
                    @Override
                    public Boolean call(Integer num) {
                        return num > 3;
                    }
                }).subscribe(onNextAction, onErrorAction, onCompletedAction);

all操作符,对源Observable发送的每一个数据根据给定的条件进行判断。如果全部符合条件,返回true,否则返回false。

②contains操作符

contains操作符实现的代码如下所示:

                Observable.just(1, 2, 3, 4).contains(2).subscribe(onNextAction, onErrorAction, onCompletedAction);

contains操作符,对源Observable发送的数据是否包含定义的选项进行判断。如果包含返回true,否则返回false。

③isEmpty操作符

isEmpty操作符实现的代码如下所示:

                Observable.just(1, 2, 3, 4).isEmpty().subscribe(onNextAction, onErrorAction, onCompletedAction);

isEmpty操作符,对源Observable发送的数据是否为空进行判断。如果源Observable发送的数据为空返回true,否则返回false。

④exists操作符

exists操作符实现的代码如下所示:

                Observable.just(1, 2, 3, 4).exists(new Func1() {
                    @Override
                    public Boolean call(Integer num) {
                        return num > 3;
                    }
                }).subscribe(onNextAction, onErrorAction, onCompletedAction);

exists操作符,对源Observable发送的单独一个数据根据给定的条件进行判断。如果有一个数据符合条件,返回true,否则返回false。

⑤sequenceEqual操作符

sequenceEqual操作符实现的代码如下所示:

                Observable.sequenceEqual(Observable.just(1, 2, 3, 4), Observable.just(1))
                          .subscribe(onNextAction, onErrorAction, onCompletedAction);

sequenceEqual操作符,对两个Observable进行判断,两个Observable相同时返回true,否则返回false。这里包含两个Observable的数据,发射顺序,终止状态是否相同。

8、条件操作符

RxJava——操作符篇_第24张图片
图2.8 条件操作符

①amb操作符

amb操作符实现的代码如下所示:

                //给定多个Observable,只让第一个发送数据的Observable发送数据
                Observable
                        .amb(Observable.range(0,3).delay(2000, TimeUnit.MILLISECONDS),Observable.range(100,3))
                        .subscribe(onNextAction);

如下图所示,首先发送通知给Amb的那个,不管发射的是一项数据还是一个onError或onCompleted通知。Amb将忽略和丢弃其它所有Observables的发射物。
RxJava——操作符篇_第25张图片
图2.8.1 amb操作符示意图

②defaultIfEmpty操作符

amb操作符实现的代码如下所示:

                //如果源Observable没有发送数据,则发送一个默认数据
                Observable.create(new Observable.OnSubscribe() {
                    @Override
                    public void call(Subscriber subscriber) {
                        subscriber.onCompleted();
                    }
                }).defaultIfEmpty(404).subscribe(onNextAction,onErrorAction,onCompletedAction);

9、转换操作符

转换操作符可以将Observable转换为其它的对象或数据结构。在这里介绍如下所示三种转换操作符:
RxJava——操作符篇_第26张图片
图2.9 转换操作符的分类

①toList操作符

toList操作符实现的代码如下所示:

                //toList操作符,将源Observable发送的数据组合为一个List集合
                //然后再次在onNext方法中将转换完的List集合进行传递
                Observable.just(1, 2, 3).toList().subscribe(new Action1>() {
                    @Override
                    public void call(List numList) {
                        for (Integer i : numList) {
                            Toast.makeText(getActivity(), "i:" + i, Toast.LENGTH_SHORT).show();
                        }
                    }
                });

通常,发射多项数据的Observable会为每一项数据调用onNext方法。你可以用toList操作符改变这个行为,让Observable将多项数据组合成一个List,然后调用一次onNext方法传递整个列表。

②toSortedList操作符

toSortedList操作符实现的代码如下所示:

                //toSortedList操作符,会将源Observable发送的数据组合为一个List集合,并会按照升序的方式进行排序
                //然后再次在onNext方法中将转换完的List集合进行传递
                Observable.just(40, 10, 80, 30).toSortedList().subscribe(new Action1>() {
                    @Override
                    public void call(List numList) {
                        for (Integer i : numList) {
                            Toast.makeText(getActivity(), "i:" + i, Toast.LENGTH_SHORT).show();
                        }
                    }
                });

不同于toList操作符的是,它会对产生的列表排序,默认是自然升序。

③toMap操作符

toMap操作符实现的代码如下所示:

              //toMap操作符,将源Observable发送的数据作为Map集合中的值,需要值进行键的定义
              //将转换完毕的Map集合在onNext方法中进行发送
              Observable.just("Alex","Payne").toMap(new Func1() {
                  @Override
                  public Integer call(String s) {
                      return s.equals("Alex")?0:1;
                  }
              }).subscribe(new Action1>() {
                  @Override
                  public void call(Map convertMap) {
                      for (int i = 0; i < convertMap.size(); i++) {
                          Toast.makeText(getActivity(), convertMap.get(i), Toast.LENGTH_SHORT).show();
                      }
                  }
              });

源Observable发送的数据作为键值对中的值,我们可以提供一个用于生成Map的Key的函数,然后不同的键存储源Observable发送的不同的值。
toMap默认不在任何特定的调度器上执行。

RxJava——操作符篇_第27张图片
图2.9.3 toMap操作符示意图

三、总结

1、在本文中,我结合项目代码详细介绍了部分RxJava的操作符,局部参照:RxJava中文翻译文档。
2、本文中的案例代码已上传Github,欢迎大家star、fork。详情戳→GitHub案例代码。
3、操作符实质上就是RxJava函数式编程模式的体现,Lambda表达式并且可以进一步优化RxJava。
4、在下篇文章中我会对于RxJava进行深层次的剖析,还有RxJava结合例如Retrofit、RxBus等开源框架的内容,希望本文对你在学习RxJava的路上有所启发。

你可能感兴趣的:(RxJava——操作符篇)