Rxjava_操作符篇

一、RxJava操作符概述

RxJava中的操作符就是为了提供函数式的特性,函数式最大的好处就是使得数据处理简洁易懂。

操作符实质上就是RxJava函数式编程模式的体现,在上篇文章中,我详细阐述了RxJava中观察者模式、Iterator模式、函数式编程模式概念的解读,详情请戳→文章传送门

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

图1.1 RxJava操作符的分类

本项目案例代码已上传Github,详情戳→GitHub案例代码

图1.2 RxJava操作符案例图

二、RxJava操作符详解

1、创建操作符

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

图2.1  创建操作符的分类

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

①from操作符

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

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

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

图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);

图2.1.2 just操作符结构图

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

③interval操作符

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

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

图2.1.3 interval操作符结构图

查看interval的结构图,其只能发送Long类型的数,实质上其作用为:创建一个按固定时间间隔发射整数序列的Observable,这个序列为一个无限递增的整数序列。

需要注意的是:interval默认在computation调度器上执行。你也可以传递一个可选的Scheduler参数来指定调度器。

④range操作符

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

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

range操作符发射一个范围内的有序整数序列,并且我们可以指定范围的起始和长度

图2.1.4 range操作符参数释义

⑤repeat操作符

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

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

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

2、变换操作符

在这里我介绍如下图所示7种变换操作符,变换操作符的作用是将源Observable发送的数据进行变换。

图2.1 变换操作符的分类

①map操作符

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

//map操作符,通过指定一个Func,将Observable转换为另一个Observable对象并发送Observable.just("Alex_Payne")                  .map(newFunc1() {                      @Override                      publicStringcall(Strings) {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(newFunc1>() {              @Override              public Observable call(Strings) {returnObservable.just("My Name is:"+ s);              }        }).subscribe(onNextAction);

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

图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(newFunc1>() {              @Override              public Observable call(Strings) {returnObservable.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(newFunc1>() {@OverridepublicIterablecall(Integer number){                  ArrayList mList =newArrayList<>();                  mList.add(1000+ number);returnmList;              }          }).subscribe(onNextAction);

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

图2.2.5 flatMapIterable示意图

⑥buffer操作符

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

//buffer操作符,将原有Observable转换为一个新的Observable,这个新的Observable每次发送一组值,而不是一个个进行发送Observable.just(1,2,3,4,5,6)              .buffer(3).subscribe(newAction1>() {@Overridepublicvoidcall(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对象。

图2.2.6 buffer操作符示意图

⑦groupBy操作符

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

//groupBy操作符,可以做分组操作Observable.range(0,10).groupBy(newFunc1() {@OverridepublicIntegercall(Integer num){returnnum %3;                  }            }).subscribe(newAction1>() {@Overridepublicvoidcall(finalGroupedObservable groupedObservable){                  groupedObservable.subscribe(newAction1() {@Overridepublicvoidcall(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种。

图3.1 过滤操作符的分类

①filter操作符

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

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

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

②elementAt操作符

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

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

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

图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项数据

图2.3.4 skip操作符示意图

⑤take操作符

//take操作符,用于Observable发送的元素只取前N项Observable.range(0,5).take(2).subscribe(onNextAction);

图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(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){for(inti =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,示意图如下:

图2..3.7 throttleFirst操作符示意图

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

⑧throttleWithTimeOut操作符

//throttleWithTimeout操作符//源发射数据时,如果两次数据的发射间隔小于指定时间,就会丢弃前一次的数据,直到指定时间内都没有新数据发射时才进行发射          Observable.create(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){                        subscriber.onNext(1);try{                              Thread.sleep(500);                          }catch(InterruptedException e) {throwExceptions.propagate(e);                          }                        subscriber.onNext(2);try{                              Thread.sleep(500);                          }catch(InterruptedException e) {throwExceptions.propagate(e);                          }                          subscriber.onNext(3);try{                            Thread.sleep(1000);                          }catch(InterruptedException e) {throwExceptions.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种操作符:

图4.1 组合操作符分类

①startWith组合操作符

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

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

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

②merge组合操作符

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

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

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

图2.4.2 merge操作符示意图

需要注意的是:merge可能会让合并的Observables发射的数据交错。

在这里我将firstObservable指定在IO线程中进行发送,secondObservable没有指定线程,两者合并然后发送数据时便会产生数据交错的现象。

③concat组合操作符

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

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

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

图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,newFunc2() {                    @Override                    publicStringcall(Integer num,Stringinfo) {//在这里的转换关系为将数字与字串内容进行拼接return"数字为:"+ num +"……字符为:"+ info;                    }                }).subscribe(onNextAction);

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,newFunc2() {                    @Override                    publicStringcall(Integer num,Stringinfo) {//在这里的转换关系为将数字与字串内容进行拼接return"数字为:"+ num +"……字符为:"+ info;                    }                }).subscribe(onNextAction);

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

5、辅助操作符

辅助操作符就是处理Observable的帮助动作,在这里介绍如下5种辅助操作符。

图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发生在下图中的发送过程。

图2.5.4 Observable与Subscriber的转换关系图

⑤timeout辅助操作符

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

//timeout操作符,如果源Observable对象过了一段时间没有发送数据,timeout会以onError通知终止这个ObservableObservable.create(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){for(inti =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、错误操作符

图2.6 错误操作符的分类

①catch操作符

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

首先分析onErrorReturn的代码:

Observable.create(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){for(inti =0; i <5; i++) {if(i >3) {                                subscriber.onError(newThrowable("User Alex Defined Error"));                            }                            subscriber.onNext(i);                        }                    }                }).onErrorReturn(newFunc1() {@OverridepublicIntegercall(Throwable throwable){return404;                    }                }).subscribe(onNextAction, onErrorAction, onCompletedAction);

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

然后分析onErrorResumeNext的代码:

Observable.create(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){for(inti =0; i <5; i++) {if(i >3) {                                subscriber.onError(newThrowable("User Alex Defined Error"));                            }                            subscriber.onNext(i);                        }                    }                }).onErrorResumeNext(newFunc1>() {@OverridepublicObservable call(Throwable throwable) {returnObservable.just(100,101,102);                    }                }).subscribe(onNextAction,onErrorAction,onCompletedAction);

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

最后,分析onExceptionResumeNext的代码:

Observable.create(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){for(inti =0; i <5; i++) {if(i >3) {                                subscriber.onError(newThrowable("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(newObservable.OnSubscribe() {@Overridepublicvoidcall(Subscriber subscriber){for(inti =0; i <5; i++) {if(i >1) {                                subscriber.onError(newThrowable("User Alex Defined Error"));                            }                            subscriber.onNext(i);                        }                    }                }).retry(2).subscribe(onNextAction,onErrorAction,onCompletedAction);

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

图2.6.2 retry操作符示意图

7、布尔操作符

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

图2.7 布尔操作符分类

①all操作符

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

Observable.just(1,2,3,4).all(newFunc1() {@OverridepublicBooleancall(Integer num){returnnum >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(newFunc1() {@OverridepublicBooleancall(Integer num){returnnum >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、条件操作符

图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的发射物。

图2.8.1 amb操作符示意图

②defaultIfEmpty操作符

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

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

9、转换操作符

转换操作符可以将Observable转换为其它的对象或数据结构。在这里介绍如下所示三种转换操作符:

图2.9 转换操作符的分类

①toList操作符

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

//toList操作符,将源Observable发送的数据组合为一个List集合//然后再次在onNext方法中将转换完的List集合进行传递Observable.just(1,2,3).toList().subscribe(newAction1>() {@Overridepublicvoidcall(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(newAction1>() {@Overridepublicvoidcall(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(newFunc1() {@OverridepublicIntegercall(String s){returns.equals("Alex")?0:1;                  }              }).subscribe(newAction1>() {@Overridepublicvoidcall(Map convertMap){for(inti =0; i < convertMap.size(); i++) {                          Toast.makeText(getActivity(), convertMap.get(i), Toast.LENGTH_SHORT).show();                      }                  }              });

源Observable发送的数据作为键值对中的值,我们可以提供一个用于生成Map的Key的函数,然后不同的键存储源Observable发送的不同的值。

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

图2.9.3 toMap操作符示意图

作者:Alex_Payne

链接:https://www.jianshu.com/p/d997805b37d4

來源:简书

简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 一、RxJava操作符概述 RxJava中的操作符就是为了提供函数式的特性,函数式最大的好处就是使得数据处理简洁易...
    王帅Alex阅读 18,938评论 21 98
  • 作者: maplejaw本篇只解析标准包中的操作符。对于扩展包,由于使用率较低,如有需求,请读者自行查阅文档。 创...
    maplejaw_阅读 45,568评论 8 93
  • 注:只包含标准包中的操作符,用于个人学习及备忘参考博客:http://blog.csdn.net/maplejaw...
    小白要超神阅读 2,178评论 2 8
  • 转一篇文章 原地址:http://gank.io/post/560e15be2dca930e00da1083 前言...
    jack_hong阅读 897评论 0 2
  • 我从去年开始使用 RxJava ,到现在一年多了。今年加入了 Flipboard 后,看到 Flipboard 的...
    Jason_andy阅读 5,435评论 7 62