这一章我们接着介绍组合操作符,这类operators可以同时处理多个Observable来创建我们所需要的Observable。组合操作符主要包含: Merge StartWith Concat Zip CombineLatest SwitchOnNext Join等等。

Merge

merge(Observable, Observable)将两个Observable发射的事件序列组合并成一个事件序列,就像是一个Observable发射的一样。你可以简单的将它理解为两个Obsrvable合并成了一个Observable,合并后的数据是无序的。

我们看下面的例子,一共有两个Observable:一个用来发送字母,另一个用来发送数字;现在我们需要两连个Observable发射的数据合并。

String[] letters = new String[]{"A", "B", "C", "D", "E", "F", "G", "H"};
Observable<String> letterSequence = Observable.interval(300, TimeUnit.MILLISECONDS)
.map(new Func1<Long, String>() {
@Override
public String call(Long position) {
return letters[position.intValue()];
}
}).take(letters.length); Observable<Long> numberSequence = Observable.interval(500, TimeUnit.MILLISECONDS).take(5); Observable.merge(letterSequence, numberSequence)
.subscribe(new Observer<Serializable>() {
@Override
public void onCompleted() {
System.exit(0);
} @Override
public void onError(Throwable e) {
System.out.println("Error:" + e.getMessage());
} @Override
public void onNext(Serializable serializable) {
System.out.print(serializable.toString()+" ");
}
});

程序输出:

A 0 B C 1 D E 2 F 3 G H 4

merge(Observable[])将多个Observable发射的事件序列组合并成一个事件序列,就像是一个Observable发射的一样。

StartWith

startWith(T)用于在源Observable发射的数据前插入数据。使用startWith(Iterable<T>)我们还可以在源Observable发射的数据前插入Iterable。官方示意图:

)" title="">

startWith(Observable<T>)用于在源Observable发射的数据前插入另一个Observable发射的数据(这些数据会被插入到

源Observable发射数据的前面)。官方示意图:

)" title="">

Concat

concat(Observable<? extends T>, Observable<? extends T>) concat(Observable<? extends Observable<T>>)用于将多个obserbavle发射的的数据进行合并发射,concat严格按照顺序发射数据,前一个Observable没发射玩是不会发射后一个Observable的数据的。它和merge、startWitch和相似,不同之处在于:

  1. merge:合并后发射的数据是无序的;
  2. startWitch:只能在源Observable发射的数据前插入数据。

, Observable)、concat(Observable>)" title="">

这里我们将前面Merge操作符的例子拿过来,并将操作符换成Concat,然后我们看看执行结果:

String[] letters = new String[]{"A", "B", "C", "D", "E", "F", "G", "H"};
Observable<String> letterSequence = Observable.interval(300, TimeUnit.MILLISECONDS)
.map(new Func1<Long, String>() {
@Override
public String call(Long position) {
return letters[position.intValue()];
}
}).take(letters.length); Observable<Long> numberSequence = Observable.interval(500, TimeUnit.MILLISECONDS).take(5); Observable.concat(letterSequence, numberSequence)
.subscribe(new Observer<Serializable>() {
@Override
public void onCompleted() {
System.exit(0);
} @Override
public void onError(Throwable e) {
System.out.println("Error:" + e.getMessage());
} @Override
public void onNext(Serializable serializable) {
System.out.print(serializable.toString() + " ");
}
});

程序输出:

A B C D E F G H 0 1 2 3 4

Zip

zip(Observable, Observable, Func2)用来合并两个Observable发射的数据项,根据Func2函数生成一个新的值并发射出去。当其中一个Observable发送数据结束或者出现异常后,另一个Observable也将停在发射数据。

和前面的例子一样,我们将操作符换成了zip:

String[] letters = new String[]{"A", "B", "C", "D", "E", "F", "G", "H"};
Observable<String> letterSequence = Observable.interval(120, TimeUnit.MILLISECONDS)
.map(new Func1<Long, String>() {
@Override
public String call(Long position) {
return letters[position.intValue()];
}
}).take(letters.length); Observable<Long> numberSequence = Observable.interval(200, TimeUnit.MILLISECONDS).take(5); Observable.zip(letterSequence, numberSequence, new Func2<String, Long, String>() {
@Override
public String call(String letter, Long number) {
return letter + number;
}
}).subscribe(new Observer<String>() {
@Override
public void onCompleted() {
System.exit(0);
} @Override
public void onError(Throwable e) {
System.out.println("Error:" + e.getMessage());
} @Override
public void onNext(String result) {
System.out.print(result + " ");
}
});

程序输出:

A0 B1 C2 D3 E4

CombineLatest

comnineLatest(Observable, Observable, Func2)用于将两个Observale最近发射的数据已经Func2函数的规则进展组合。下面是官方提供的原理图:

下面这张图应该更容易理解:

List<String> communityNames = DataSimulator.getCommunityNames();
List<Location> locations = DataSimulator.getLocations(); Observable<String> communityNameSequence = Observable.interval(1, TimeUnit.SECONDS)
.map(new Func1<Long, String>() {
@Override
public String call(Long position) {
return communityNames.get(position.intValue());
}
}).take(communityNames.size());
Observable<Location> locationSequence = Observable.interval(1, TimeUnit.SECONDS)
.map(new Func1<Long, Location>() {
@Override
public Location call(Long position) {
return locations.get(position.intValue());
}
}).take(locations.size()); Observable.combineLatest(
communityNameSequence,
locationSequence,
new Func2<String, Location, String>() {
@Override
public String call(String communityName, Location location) {
return "小区名:" + communityName + ", 经纬度:" + location.toString();
}
}).subscribe(new Observer<String>() {
@Override
public void onCompleted() {
System.exit(0);
} @Override
public void onError(Throwable e) {
System.out.println("Error:" + e.getMessage());
} @Override
public void onNext(String s) {
System.out.println(s);
}
});

程序输出:

小区名:竹园新村, 经纬度:(21.827, 23.323)
小区名:康桥半岛, 经纬度:(21.827, 23.323)
小区名:康桥半岛, 经纬度:(11.923, 16.309)
小区名:中粮·海景壹号, 经纬度:(11.923, 16.309)
小区名:中粮·海景壹号, 经纬度:(22.273, 53.623)
小区名:浦江名苑, 经纬度:(22.273, 53.623)
小区名:南辉小区, 经纬度:(22.273, 53.623)

SwitchOnNext

switchOnNext(Observable<? extends Observable<? extends T>>用来将一个发射多个小Observable的源Observable转化为一个Observable,然后发射这多个小Observable所发射的数据。如果一个小的Observable正在发射数据的时候,源Observable又发射出一个新的小Observable,则前一个Observable发射的数据会被抛弃,直接发射新

的小Observable所发射的数据。

结合下面的原理图大家应该很容易理解,我们可以看到下图中的黄色圆圈就被丢弃了。

>)" title="">

Join

join(Observable, Func1, Func1, Func2)我们先介绍下join操作符的4个参数:

  • Observable:源Observable需要组合的Observable,这里我们姑且称之为目标Observable;
  • Func1:接收从源Observable发射来的数据,并返回一个Observable,这个Observable的声明周期决定了源Obsrvable发射出来的数据的有效期;
  • Func1:接收目标Observable发射来的数据,并返回一个Observable,这个Observable的声明周期决定了目标Obsrvable发射出来的数据的有效期;
  • Func2:接收从源Observable和目标Observable发射出来的数据,并将这两个数据组合后返回。

所以Join操作符的语法结构大致是这样的:onservableA.join(observableB, 控制observableA发射数据有效期的函数, 控制observableB发射数据有效期的函数,两个observable发射数据的合并规则)

join操作符的效果类似于排列组合,把第一个数据源A作为基座窗口,他根据自己的节奏不断发射数据元素,第二个数据源B,每发射一个数据,我们都把它和第一个数据源A中已经发射的数据进行一对一匹配;举例来说,如果某一时刻B发射了一个数据“B”,此时A已经发射了0,1,2,3共四个数据,那么我们的合并操作就会把“B”依次与0,1,2,3配对,得到四组数据: [0, B] [1, B] [2, B] [3, B]

再看看下面的图是不是好理解了呢?!

读懂了上面的文字,我们再来写段代码加深理解。

final List<House> houses = DataSimulator.getHouses();//模拟的房源数据,用于测试

//用来每秒从houses总取出一套房源并发射出去
Observable<House> houseSequence =
Observable.interval(1, TimeUnit.SECONDS)
.map(new Func1<Long, House>() {
@Override
public House call(Long position) {
return houses.get(position.intValue());
}
}).take(houses.size());//这里的take是为了防止houses.get(position.intValue())数组越界 //用来实现每秒发送一个新的Long型数据
Observable<Long> tictoc = Observable.interval(1, TimeUnit.SECONDS); houseSequence.join(tictoc,
new Func1<House, Observable<Long>>() {
@Override
public Observable<Long> call(House house) {
return Observable.timer(2, TimeUnit.SECONDS);
}
},
new Func1<Long, Observable<Long>>() {
@Override
public Observable<Long> call(Long aLong) {
return Observable.timer(0, TimeUnit.SECONDS);
}
},
new Func2<House, Long, String>() {
@Override
public String call(House house, Long aLong) {
return aLong + "-->" + house.getDesc();
}
}
).subscribe(new Observer<String>() {
@Override
public void onCompleted() {
System.exit(0);
} @Override
public void onError(Throwable e) {
System.out.println("Error:"+e.getMessage());
} @Override
public void onNext(String s) {
System.out.println(s);
}
});

程序输出:

0-->中粮海景壹号新出大平层!总价4500W起
1-->中粮海景壹号新出大平层!总价4500W起
1-->满五唯一,黄金地段
2-->中粮海景壹号新出大平层!总价4500W起
2-->满五唯一,黄金地段
2-->一楼自带小花园
3-->一楼自带小花园
3-->毗邻汤臣一品
4-->毗邻汤臣一品
4-->顶级住宅,给您总统般尊贵体验
5-->顶级住宅,给您总统般尊贵体验
5-->顶层户型,两室一厅
6-->顶层户型,两室一厅
6-->南北通透,豪华五房
7-->南北通透,豪华五房

通过转换操作符过滤操作符组合操作符三个篇幅将RxJava主要的操作符也介绍的七七八八了。更多操作符的介绍建议大家去查阅官方文档,并自己动手实践一下。这一系列的文章也会持续更新,欢迎大家保持关注!:)

Demo源码地址:https://github.com/BaronZ88/HelloRxJava

如果你喜欢我的文章,就关注下我的知乎专栏或者在 GitHub 上添个 Star 吧!

RxJava系列5(组合操作符)的更多相关文章

  1. RxJava系列4(过滤操作符)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  2. RxJava系列3(转换操作符)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  3. RxJava系列番外篇:一个RxJava解决复杂业务逻辑的案例

    之前写过一系列RxJava的文章,也承诺过会尽快有RxJava2的介绍.无奈实际项目中还未真正的使用RxJava2,不敢妄动笔墨.所以这次还是给大家分享一个使用RxJava1解决问题的案例,希望对大家 ...

  4. RxJava系列7(最佳实践)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  5. RxJava系列6(从微观角度解读RxJava源码)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  6. RxJava系列2(基本概念及使用介绍)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  7. RxJava系列1(简介)

    RxJava系列1(简介) RxJava系列2(基本概念及使用介绍) RxJava系列3(转换操作符) RxJava系列4(过滤操作符) RxJava系列5(组合操作符) RxJava系列6(从微观角 ...

  8. RxJava系列之二 变换类操作符具体解释1

    1.回想 上一篇文章我们主要介绍了RxJava , RxJava 的Observables和 RxJava的just操作符.以及RxJava一些经常使用的操作. 没看过的抓紧点我去看吧. 事实上RxJ ...

  9. RxJava【过滤】操作符 filter distinct throttle take skip first MD

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

随机推荐

  1. 读取超大Excel(39万行数据)

    有个学长需要处理Excel数据,Excel数据共有39W,将数据读取后处理并导出数据.最开始尝试了 NPOI ,发现NPOI 并不能完成该项任务,随后尝试引用的com组件:Microsoft.Offi ...

  2. serializeArray()获取的表单参数转化成json格式的对象

    目标:将serializeArray()这个方法获取的表单对象  转换成json格式 function serializeObject(){ //easyui提交表单 $('#form').form( ...

  3. 通过Performance Log确定磁盘有性能问题?

    一些比较重要的performance counter: Counter Description LogicalDisk\ % Free Space 报告磁盘空间中未被分配的空间占逻辑卷中总可用空间的百 ...

  4. iframe标签的定时刷新

    由于有个项目是大数据类型的,需要时时展现数据,这就出现了这个需求,页面不断刷新,这个其实很简单了,window.location.reload(); 这个就轻松搞定了,但是灵机一动,加上个控制吧,这下 ...

  5. UVA 10305 Ordering Tasks(拓扑排序的队列解法)

    题目链接: https://vjudge.net/problem/UVA-10305#author=goodlife2017 题目描述 John有n个任务,但是有些任务需要在做完另外一些任务后才能做. ...

  6. Object.defineProperty实现数据绑定

    1.Object.defineProperty方法 Object.defineProperty(obj, prop, descriptor); (1)参数:  obj:目标对象 prop:需要定义的属 ...

  7. pycharm 的安装及selenium环境的搭建

    6.呵呵哒,前面写了一篇pycharm的安装,,结果自己都看不懂了,copy了别人的,,,自己现在再写一遍,这篇文章主要写pycharm 的安装及selenium 环境的搭建,selenium的搭建不 ...

  8. 一周总结:AutoEncoder、Inception 、模型搭建及下周计划

    一周总结:AutoEncoder.Inception .模型搭建及下周计划   1.AutoEncoder: AutoEncoder: 自动编码器就是一种尽可能复现输入信号的神经网络:自动编码器必须捕 ...

  9. JavaScript(第三十三天)【总结:封装基础前端框架】

    源码地址:https://github.com/whisper540/Base

  10. Ionic3的HTTP请求方法

    Ionic的http请求方法,一种是使用Ionic的Native的Http方法,另一种是使用Angular的Http请求方法. 第一种真的是看着文档都实现不了,很奇怪的错(官网文档:https://i ...