RxJava 的合并操作符主要包括如下几个:
- startWith():在数据序列的开头增加一项数据
- merge():将多个 Observable 合并为一个
- mergeDelayError():合并多个 Observable,让没有错误的 Observable 都完成后在发射错误通知
- zip():使用一个函数组合多个 Observable 发射的数据集合,然后再发射这个结果
- combineLatest():当两个 Observable 中的任何一个发射了一个数据时,通过一个指定的函数组合每个 Observable 发射的最新数据(一共两个数据),然后发射这个函数的结果
- join()、groupJoin():无论何时,如果一个 Observable 发射了一个数据项,就需要在另一个 Observable 发射的数据项定义的时间窗口内,将两个 Observable 发射的数据合并发射
- switchOnNext():将一个发射 Observable 的 Observable 转换成另一个 Observable,后者发射这些 Observable 最近发射的数据
RxJava 的连接操作符,主要是 ConnectableObservable 所使用的操作符和 Observable 所使用的操作符
- ConnectableObservable.connect():指示一个可连接的 Observable 开始发射数据
- Observable.publish():将一个 Observable 转换为一个可连接的 Observable
- Observable.replay():确保所有的订阅者看到相同的数据序列,即使他们在 Observable 开始发射数据之后才订阅
- ConnectableObservable.refCount():让一个可连接的 Observable 表现的像一个普通的 Observable
1. merge 和 zip
- merge 操作符 合并多个 Observable 的发射物,使得它们就像是单个的 Observable 一样。
Observable<Integer> odds = Observable.just(1, 3, 5);
Observable<Integer> evens = Observable.just(2, 4, 6);
Observable.merge(odds, evens)
.subscribe(System.out::println);
复制代码
执行结果:
1
3
5
2
4
6
复制代码
merge 是按照时间线并行的。如果传递给 merge 的任何一个 Observable 发射了 onError 通知终止,则 merge 操作符生成的 Observable 也会立即以 onError 通知终止。如果想让它继续发射数据,知道最后才报告错误,则可以使用 mergeDelayError 操作符。 merge 操作符最多只能合并 4 个被观察者,如果需要合并更多个被观察者,则可以使用 mergeArray 操作符。
- zip 操作符 通过一个函数将多个 Observable 的发射物结合到一起,基于这个函数的结果为每个结合体发射单个数据项。它按照严格的顺序应用这个函数,只发射与发射数据项最少的那个 Observable 一样多的数据。 zip 的最后一个参数接收每个 Observable 发射的一项数据,返回被压缩后的数据,他可以接收 1~9 个参数;一个 Observable 序列,或者一些发射 Observable 的 Observable。
Observable<Integer> odds = Observable.just(1, 3, 5);
Observable<Integer> evens = Observable.just(2, 4, 6);
Observable.zip(odds, evens,
(BiFunction<Integer, Integer, Object>) (integer, integer2) -> integer + integer2)
.subscribe(System.out::println);
复制代码
zip 只发射与发射数据项最少的那个 Observable 一样多的数据。这里 BiFunction 相当于一个合并函数,并不一定要返回 Integer 类型,可以根据业务需要返回合适的类型。
2. combineLatest 和 join
- combineLatest 操作符 combineLatest 操作符的行为类似于 zip,但是只有当原始的 Observable 中的每一个都发射了一条数据时 zip 才发射数据,而 combineLatest 则是当原始 Observable 中任意一个发射了数据时就发射一条数据。当原始 Observable 的任何一个发射了一个数据是,combineLatest 使用一个函数结合它们最近发射的数据,然后发射这个函数的返回值。
Observable<Integer> odds = Observable.just(1, 3, 5);
Observable<Integer> evens = Observable.just(2, 4, 6);
Observable.combineLatest(odds, evens,
(BiFunction<Integer, Integer, Object>) (integer, integer2) -> integer + integer2)
.subscribe(System.out::println);
复制代码
执行结果
7
9
11
复制代码
- join 操作符 join 操作符结合两个 Observable 发射的数据,基于时间窗口(针对每条数据特定的原则)选择待集合的数据项。讲这些时间窗口时限为一些 Observable,它们的生命周期从任何一条 Observable 发射每一条数据开始。当这个定义时间窗口的 Observable 发射了一条数据或者完成时,与这条数据关联的窗口也会关闭。只要这条数据的窗口是打开的,他就继续结合其他 Observable 发射的任何数据项。 join(Observable, Function, Function, BiFunction) 有四个参数,用途如下:
- Observable:源 Observable 需要组合的 Observable,这里可以称之为目标 Observable。
- Function:接收从源 Observable 发射来的数据,并返回一个 Observable,这个 Observable 的生命周期决定了源 Observable 发射数据的有效期
- Function:接收目标 Observable 发射的数据,并返回一个 Observable,这个 Observable 的生命周期决定了目标 Observable 发射数据的有效期
- BiFunction:接受从源 Observable 和目标 Observable 发射的数据,并将这两个数据组合后返回。
join 操作符的效果类似排列组合,把第一个数据源 A 作为基座窗口,他根据自己的节奏不断发射数据元素;第二个数据源 B,每发射一个数据,都把它与第一个数据源 A 中已经发射的数据一对一匹配。
3. startWith
在数据序列的开头插入一条指定的项。如果想让一个 Observable 在发射数据之前县发射一个指定的数据序列,则可以使用 startWith 操作符。如果想在一个 Observable 发射数据的末尾最佳一个数据序列,则可以使用 concat 操作符。
4. connect、push 和 refCount
connect 和 refCount 是 ConnectableObservable 所使用的操作符。ConnectableObservable 继承自 Observable,然而它并不是在调用 subscribe() 的时候才发射数据,而是只有对其使用 connect 操作符时它才会发射数据,所以可以用来更灵活地控制数据发射的实际。 push 操作符是将普通的 Observable 转换成 ConnectableObservable。 connect 操作符是用来触发 ConnectableObservable 发射数据的。 refCount 操作符是将 ConnectableObservable 转换成普通的 Observable,同时又保持 Hot Observable 的特性。当出现第一个订阅者时,refCount 会调用 connect()。每个订阅者每次都会接收到同样的数据,但是当所有订阅者都取消订阅(dispose)时,refCount 会自动 dispose 上游的 Observable。 所有订阅者都取消订阅后,则数据流停止。如果重新订阅则数据流重新开始,如果不是所有的订阅者都取消了订阅,而是部分取消了,则部分订阅者/观察者重新开始订阅时,不会从头开始数据流。
5. replay
保证所有的观察者收到相同的数据序列,即使它们在 Observable 开始发射数据之后才订阅。replay 操作符返回一个 ConnectableObservable 对象,并且可以缓存发射过的数据,这样即使有订阅者在数据发射后才进行订阅,也能收到之前发射过的数据。不过使用 replay 操作符最好还是先限定缓存的大小,否则缓存的数据太多时会占用很大一块内存。对缓存的控制可以从空间和时间两个方面来实现。 replay 有多个接受不同参数的重载方法,有的可以指定 replay 的最大缓存数,有的可以指定调度器,ConnectableObservable 的线程切换只能通过 replay 操作符实现,普通 Observable 的 subscribeOn() 和 observerOn() 在 ConnectableObservable 中不起作用。replay 操作符可以通过指定线程的方式来切换线程。