天天看点

RxJava操作符系列二(下)

RxJava操作符系列二(下)

接上文

输出日志信息

call:2 concatmap rxnewthreadscheduler-5 

onnext: concatmap 101 concatmap 

call:2 concatmap rxnewthreadscheduler-6 

onnext: concatmap 102 concatmap 

call:2 concatmap rxnewthreadscheduler-7 

onnext: concatmap 103 concatmap 

oncompleted: concatmap  

通过该操作符和flatmap输出的日志信息,很容易看出flatmap并没有保证数据源的顺序性,但是concatmap操作符保证了数据源的顺序性。在应用中,如果你对数据的顺序性有要求的话,就需要使用concatmap。若没有要求,二者皆可使用。

switchmap

当原始observable发射一个新的数据(observable)时,它将取消订阅并停止监视产生执之前那个数据的observable,只监视当前这一个.

integer[] integers = {1, 2, 3}; 

observable.from(integers).switchmap(new func1>() { 

            @override 

            public observable call(integer integer) { 

                log.e(tag, "call: switchmap" + thread.currentthread().getname()); 

                //如果不通过subscribeon(schedulers.newthread())在在子线程模拟并发操作,所有数据源依然会全部输出,也就是并发操作此操作符才有作用 

                //若在此通过thread。sleep()设置等待时间,则输出信息会不一样。相当于模拟并发程度 

                return observable.just((integer + 100) + "switchmap").subscribeon(schedulers.newthread()); 

            } 

        }).observeon(androidschedulers.mainthread()).subscribe(new subscriber() { 

            public void oncompleted() { 

                log.e(tag, "oncompleted: switchmap"); 

            public void onerror(throwable e) { 

                log.e(tag, "onerror: switchmap"); 

            public void onnext(string s) { 

                log.e(tag, "onnext: switchmap "+s); 

        });  

call: switchmapmain 

onnext: switchmap 106switchmap 

oncompleted: switchmap  

当数据源较多时,并不一定是只输出最后一项数据,有可能输出几项数据,也可能是全部。

groupby

看到这个词你就应该想到了这个操作符的作用,就是你理解的含义,他将数据源按照你的约定进行分组。我们通过groupby实行将1到10的数据进行就划分,代码如下

observable.range(1, 10).groupby(new func1() { 

            public boolean call(integer integer) { 

                return integer % 2 == 0; 

        }).subscribe(new subscriber>() { 

                log.e(tag, "oncompleted:1 "); 

                log.e(tag, "onerror:1 "); 

            public void onnext(groupedobservable booleanintegergroupedobservable) { 

                booleanintegergroupedobservable.tolist().subscribe(new subscriber>() { 

                    @override 

                    public void oncompleted() { 

                        log.e(tag, "oncompleted:2 " ); 

                    } 

                    public void onerror(throwable e) { 

                        log.e(tag, "onerror:2 "); 

                    public void onnext(list integers) { 

                        log.e(tag, "onnext:2 "+integers); 

                }); 

onnext:2 [1, 3, 5, 7, 9] 

oncompleted:2 

onnext:2 [2, 4, 6, 8, 10] 

oncompleted:1  

在上面代码中booleanintegergroupedobservable变量有一个getkey()方法,该方法返回的是分组的key,他的值就是groupby方法call回调所用函数的值,在上面也就是integer % 2 == 0的值,及true和false。有几个分组也是有此值决定的。

scan

操作符对原始observable发射的第一项数据应用一个函数,然后将那个函数的结果作为自己的第一项数据发射。它将函数的结果同第二项数据一起填充给这个函数来产生它自己的第二项数据。它持续进行这个过程来产生剩余的数据序列。

例如计算1+2+3+4的和

observable.range(1,4).scan(new func2() { 

            public integer call(integer integer, integer integer2) { 

                log.e(tag, "call: integer:"+integer+"  integer2 "+integer2); 

                return integer+integer2; 

        }).subscribe(new subscriber() { 

                log.e(tag, "oncompleted: "); 

                log.e(tag, "onerror: " ); 

            public void onnext(integer integer) { 

                log.e(tag, "onnext: "+integer ); 

onnext: 1 

call: integer:1  integer2 2 

onnext: 3 

call: integer:3  integer2 3 

onnext: 6 

call: integer:6  integer2 4 

onnext: 10 

oncompleted:  

对于scan有一个重载方法,可以设置一个初始值,如上面代码,初始值设置为10,只需将scan加个参数scan(10,new func2)。

buffer

操作符将一个observable变换为另一个,原来的observable正常发射数据,变换产生的observable发射这些数据的缓存集合,如果原来的observable发射了一个onerror通知,buffer会立即传递这个通知,而不是首先发射缓存的数据,即使在这之前缓存中包含了原始observable发射的数据。

示例代码

observable.range(10, 6).buffer(2).subscribe(new subscriber>() { 

                log.e(tag, "onerror: "); 

            public void onnext(list integers) { 

                log.e(tag, "onnext: " + integers); 

onnext: [10, 11] 

onnext: [12, 13] 

onnext: [14, 15] 

上面一次性订阅两个数据,如果设置参数为6,就一次性订阅。buffer的另一重载方法buffer(count, skip)从原始observable的第一项数据开始创建新的缓存(长度count),此后每当收到skip项数据,用count项数据填充缓存:开头的一项和后续的count-1项,它以列表(list)的形式发射缓存,取决于count和skip的值,这些缓存可能会有重叠部分(比如skip count时)。具体执行结果,你可以设置不同的skip和count观察输出日志,查看执行结果及流程。

window

window和buffer类似,但不是发射来自原始observable的数据包,它发射的是observables,这些observables中的每一个都发射原始observable数据的一个子集,最后发射一个oncompleted通知。

observable.range(10, 6).window(2).subscribe(new subscriber>() { 

                log.e(tag, "oncompleted1: "); 

                log.e(tag, "onerror1: "); 

            public void onnext(observable integerobservable) { 

                log.e(tag, "onnext1: "); 

                tv1.append("\n"); 

                integerobservable.subscribe(new subscriber() { 

                        log.e(tag, "oncompleted2: "); 

                        log.e(tag, "onerror2: "); 

                    public void onnext(integer integer) { 

                        log.e(tag, "onnext2: "+integer); 

onnext2: 10 

onnext2: 11 

oncompleted2: 

onnext2: 12 

onnext2: 13 

onnext2: 14 

onnext2: 15 

oncompleted1:  

window和buffer一样也有不同的重载方法。这两个操作符相对其他操作符不太容易理解,可以去rxjava github理解,里面有图示解析。当然最好的理解方式就是通过更改变量的值,去观察输出的日志信息。

好了,这篇文章就介绍到这里。若文中有错误的地方,欢迎指正。谢谢。

本文作者:佚名

来源:51cto

继续阅读