简要:
需求了解:
对于 Observable 发射的数据有的时候可能不满足我们的要求,或者需要转化为其他类型的数据,比如:缓存,数据类型转化,数据拦截等。此时可以使用 Rx 中的一些对于数据操作的操作进行数据的变换,方便我们的开发。
执行变换的操作方法:
- Buffer:它定期从Observable收集数据到一个集合,然后把这些数据集合打包发射,而不是一次发射一个
- Map:对序列的每一项都应用一个函数来变换Observable发射的数据序列
- FlatMap,FlatMapIterable,ConcatMap:将Observable发射的数据集合变换为Observables集合,然后将这些Observable发射的数据平铺化的放进一个单独的 Observable
- SwitchMap:将Observable发射的数据集合变换为Observables集合,然后只发射这些Observables最近发射的数据
- Window:定期将来自Observable的数据分拆成一些Observable窗口,然后发射这些窗口,而不是每次发射一项
- GroupBy:将Observable分拆为Observable集合,将原始Observable发射的数据按 Key
分组,每一个Observable发射一组不同的数据 - Scan:对Observable发射的每一项数据应用一个函数,然后按顺序依次发射每一个值
- Cast:在发射之前强制将Observable发射的所有数据转换为指定类型
1. Buffer
定期收集Observable的数据放进一个数据包裹(缓存),然后发射这些数据包裹,而不是一次发射一个值。
Buffer 操作符将一个Observable变换为另一个,原来的Observable正常发射数据,变换产生 的Observable发射这些数据的缓存集合。 Buffer 操作符在很多语言特定的实现中有很多种变 体,它们在如何缓存这个问题上存在区别。
Window 操作符与 Buffer 类似,但是它在发射之前把收集到的数据放进单独的Observable, 而不是放进一个数据结构。
注意: 如果原来的Observable发射了一个 onError 通知, Buffer 会立即传递这个通知,而不是首先发射缓存的数据,即使在这之前缓存中包含了原始Observable发射的数据。
在RxJava中的一些 Buffer 的操作如下:
1.1 buffer(count)
以列表(List)的形式发射非重叠的缓存,每一个缓存至多包含来自原始 Observable 的 count
项数据(最后发射的列表数据可能少于count项)。
实例代码:
// 1. buffer(count)
// 以列表(List)的形式发射非重叠的缓存,
// 每一个缓存至多包含来自原始 Observable的count项数据(最后发射的列表数据可能少于count项)
Observable.range(1, 10)
.buffer(3)
.subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> t) throws Exception {
System.out.println("--> bufferr(1) accept: " + t);
}
});
输出:
--> bufferr(1) accept: [1, 2, 3]
--> bufferr(1) accept: [4, 5, 6]
--> bufferr(1) accept: [7, 8, 9]
--> bufferr(1) accept: [10]
Javadoc: buffer(count)
1.2 buffer(boundary)
开始创建一个List
收集原始 Observable 数据,监视一个名叫 boundary
的Observable,每当这个Observable发射了一个值,它就创建一个新的 List
开始收集来自原始Observable的数据并发射原来已经收集数据的 List
, 当 boundary
Observable 发送了完成通知,会将此时还未发送的 List 发送。
注意: 所有发送的 List 可能没有收集到数据,此时数据的收集可能并不会完整收集所有原始 Observable 数据。
实例代码:
// 2. buffer(boundary) 监视一个名叫boundary的Observable,
// 开始创建一个List收集原始 Observable 数据,监视一个名叫boundary的Observable,
// 每当这个Observable发射了一个值,它就创建一个新的List开始收集来自原始Observable的数据并发射原来已经收集数据的List,
// 当boundary发送了完成通知,会将此时还未发送的 List 发送。
// 所有发送的 List 可能没有收集到数据,此时数据的收集可能并不会完整收集所有原始Observable数据。
Observable.range(1, 10000)
.buffer(Observable.timer(1, TimeUnit.MILLISECONDS)) // 1毫秒后开始接受原始数据
.subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> t) throws Exception {
System.out.println("--> accept(2): " + t.size()); // 每次收集的数据序列个数
}
});
输出:
--> accept(2): 2858
--> accept(2): 5471
Javadoc: buffer(boundary)
1.3 buffer(count, skip)
从原始Observable的第一项数据开始创建新的缓存,此后每当收 到 skip
项数据,用 count
项数据填充缓存:开头的一项和后续的 count-1 项,它以列表 (List)的形式发射缓存,取决于 count 和 skip 的值,这些缓存可能会有重叠部分(比如skip < count时),也可能会有间隙(比如skip > count时)。
解析: 在指定的数据序列中移动指针
来获取缓存数据:指针每次移动 skip
个数据长度,每次缓存指针位置及后面count
个数据,指针初始位置在原始数据的第一个(存在的情况下)。
实例代码:
// 3. buffer(int count, int skip)
// 在指定的数据中移动指针来获取缓存数据:指针每次移动1个数据长度,每次缓存3个数据
Observable.range(1, 5)
.buffer(3, 1)
.subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> t) throws Exception {
System.out.println("--> bufferr(3) accept: " + t);
}
});
输出:
--> bufferr(3) accept: [1, 2, 3]
--> bufferr(3) accept: [2, 3, 4]
--> bufferr(3) accept: [3, 4, 5]
--> bufferr(3) accept: [4, 5]
--> bufferr(3) accept: [5]
Javadoc: buffer(count, skip)
1.4 buffer(timespan, TimeUnit)
定期以 List 的形式发射新的数据,在每个时间段,收集来自原始 Observable 的数据(从前面一个数据包裹之后,或者如果是第一个数据包裹,从有观察者订阅原来的 Observale 之后开始)。还有另一个版本的 buffer 接受一个 Scheduler 参数。
解析: 每隔 timespan
时间段以 List
的形式收集原始Observable的数据
实例代码:
// 4. buffer(long timespan, TimeUnit unit)
// 每隔timespan时间段以list的形式收集数据
Observable.range(1, 50000)
.buffer(1, TimeUnit.MILLISECONDS) // 每隔1毫秒收集一次原始序列数据
.subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> t) throws Exception {
System.out.println("--> bufferr(4) accept: " + t.size()); // 每次收集的数据序列个数
}
});
输出:
--> bufferr(4) accept: 2571
--> bufferr(4) accept: 5457
--> bufferr(4) accept: 13248
--> bufferr(4) accept: 12755
--> bufferr(4) accept: 9543
--> bufferr(4) accept: 6426
注意:
buffer(timespan,TimeUnit)
默认情况下会使用 computation 调度器
Javadoc: buffer(timespan,TimeUnit)
Javadoc: buffer(timespan,TimeUnit,Scheduler)
1.5 buffer(timespan, TimeUnit, count)
每当收到来自原始 Observable
的 count
项数据,或者每过了一段指定 timespan
时间后, 就以 List 的形式发射这期间的数据,即使数据项少于 count 项。还有另一个版本的 buffer 接受一个 Scheduler
参数。
实例代码:
// 5. buffer(long timespan, TimeUnit unit, int count)
// 每隔1毫秒缓存50个数据
Observable.range(1, 1000)
.buffer(1, TimeUnit.MILLISECONDS, 50) // 每隔1毫秒收集50个数据序列
.subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> t) throws Exception {
System.out.println("--> bufferr(5) accept: " + t.size()); // 每次收集的数据序列个数
}
});
输出:
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 20
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 50
--> bufferr(5) accept: 4
--> bufferr(5) accept: 50
--> buf