简要:
需求了解:
对于数据的观察以及处理过程中往往有需要过滤一些不需要的数据的需求,比如防抖(防止快速操作),获取第一项、指定序列项或者最后一项的需要,获取指定时间内的有效数据等。Rx中提供了丰富的数据过滤处理的操作方法。
可用于过滤和选择Observable发射的数据序列的方法:
- Debounce:过滤发射速率较快的数据项,防抖操作。
- Throttle: 对数据序列进行限流操作,可以指定获取周期内的指定数据项,也可以用于防抖。
- Sample: 允许通过将序列划分为时间片段收集数据,并从每片中取出一个值来稀疏序列。
- Distinct: 过滤掉重复数据。
- Skip: 跳过指定的N项数据。
- Filter: 通过函数指定过滤的数据。
- First: 只发射第一项或者满足某个条件的第一项数据。
- Single: 与 first 类似,但是如果原始Observable在完成之前不是正好发射一次数据,它会抛出一个NoSuchElementException 的异常通知。
- ElementAt: 获取原始Observable发射的数据序列指定索引位置的数据项,然后当做自己的唯一数据发射。
- ignoreElements: 不发射任何数据,只发射Observable的终止通知。
- Last: 只发射最后一项(或者满足某个条件的最后一项)数据。
- Take: 只返回Observable发送数据项序列前面的N项数据,忽略剩余的数据。
- TakeLast: 只发射Observable发送数据项序列的后N项数据,忽略其他数据。
- ofType: 过滤一个Observable只返回指定类型的数据。
1. Debounce
仅在过了一段指定的时间还没发射数据时才发射一个数据。Debounce
操作符会过滤掉发射速率过快的数据项。
提示: 操作默认在 computation 调度器上执行,但是你可以指定其它的调度器。
1.1 debounce(timeout, unit)
指定每个数据发射后在 timeout
时间内,原始数据序列中没有下一个数据发射时,发射此项数据,否则丢弃这项数据。此操作与 throttleWithTimeout
方法相同。
注意: 这个操作符会在原始数据的 onCompleted
时候直接发射发射数据,不会因为限流而丢弃数据。
实例代码:
// 1. debounce(long timeout, TimeUnit unit)
// 发送一个数据,如果在包含timeout时间内,没有第二个数据发射,那么就会发射此数据,否则丢弃此数据
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1); // 下一个数据到此数据发射, 30 < timeout --> skip
Thread.sleep(30);
emitter.onNext(2); // 下一个数据到此数据发射, 100 > timeout --> deliver
Thread.sleep(100);
emitter.onNext(3); // 下一个数据到此数据发射, 50 = timeout --> skip:
Thread.sleep(50);
emitter.onNext(4); // 下一个数据到此数据发射, onCompleted --> deliver
emitter.onComplete();
}
}).debounce(50, TimeUnit.MILLISECONDS) // 指定防抖丢弃时间段为50毫秒
// .debounce(50, TimeUnit.MILLISECONDS, Schedulers.trampoline()) // 指定调度为当前线程排队
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer t) throws Exception {
System.out.println("--> accept debounce(1-1): " + t);
}
});
输出:
--> accept debounce(1-1): 2
--> accept debounce(1-1): 4
Javadoc: debounce(timeout, unit)
Javadoc: debounce(timeout, unit, scheduler)
1.2 debounce(debounceSelector)
原始数据发射每一个序列都通过绑定监听debounceSelector
的数据通知,在debounceSelector
数据发送前,如果有下一个数据,则丢弃当前项数据,继续监视下一个数据。
注意: 这个操作符会在原始数据的 onCompleted
时候直接发射发射数据,不会因为限流而丢弃数据。
实例代码:
// 2. debounce(debounceSelector)
// 原始数据发射每一个序列的通过监听debounceSelector的数据通知,
// 在debounceSelector数据发送前,如果有下一个数据,则丢弃当前项数据,继续监视下一个数据
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1); // skip --> debounceSelector is no emitter(<2s)
Thread.sleep(1000);
emitter.onNext(2); // skip --> debounceSelector is no emitter(<2s)
Thread.sleep(200);
emitter.onNext(3); // deliver --> debounceSelector is emitter(>2s)
Thread.sleep(2500);
emitter.onNext(4); // skip --> debounceSelector is no emitter(=2s)
Thread.sleep(2000);
emitter.onNext(5); // deliver --> onComplete
Thread.sleep(500);
emitter.onComplete();
}
}).debounce(new Function<Integer, ObservableSource<Long>>() {
@Override
public ObservableSource<Long> apply(Integer t) throws Exception {
System.out.println("--> apply(1-2): " + t);
// 设置过滤延迟时间为2秒,此时返回的Observable从订阅到发送数据时间段即为timeout
return Observable.timer(2, TimeUnit.SECONDS)
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(Disposable t) throws Exception {
// 开始订阅,监听数据的发送来过滤数据
System.out.println("--> debounceSelector(1-2) is onSubscribe!");
}
}).doOnDispose(new Action() {
@Override
public void run() throws Exception {
// 发射数据后,丢弃当前的数据,解除当前绑定
System.out.println("--> debounceSelector(1-2) is unSubscribe!");