1.过滤操作符的作用:过滤/筛选 被观察者(Observable)发送的事件 以及 观察者(Observer)接收的事件
rxjava2中的常见的过滤操作符有以下的常见类型:
2.根据指定条件过滤事件
需求场景为:通过设置指定的过滤条件,当且仅当该事件满足条件,就将该事件过滤(不发送)
2.1 filter()过滤操作符
//过滤操作符之filter()
//filter()过滤操作符 主要是过掉满足特定条件的事件
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e)
throws Exception
{
e.onNext(1);
e.onNext(2);
e.onNext(3);
e.onNext(4);
e.onNext(5);
e.onNext(6);
e.onComplete();
}
//通过filter操作符来进行特定事件的过滤
}).filter(new Predicate<Integer>() {
//在test方法中通过返回的布尔值来决定是否过滤掉当前的事件
//false 过滤掉 true继续发送
@Override
public boolean test(@NonNull Integer integer)
throws Exception
{
//过滤掉所有数中的奇数
return integer % 2 == 0;
}
}).subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe: 开始采用subscribe连接 thread = " + Thread.currentThread().getName());
}
@Override
public void onNext(Integer integer) {
Log.d(TAG, "onNext: " + integer + " thread = " + Thread.currentThread().getName());
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError: " + e.getMessage() + " thread = " + Thread.currentThread().getName());
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete: thread = " + Thread.currentThread().getName());
}
});
打印结果:
2.2 ofType() 筛选符
//ofType()操作符
//筛选过滤处满足指定数据类型的数据
Observable.just(1,"hello",false,2.0f,300l,99)
//通过ofType操作符 来筛选获得Integer类型的数据
.ofType(Integer.class)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer s)
throws Exception
{
Log.d(TAG, "accept: ofType 筛选后的值为: " + s);
}
});
打印结果:
2.3 skip() / skipLast()
//skip() / skipLast()操作符
//skip()和skipLast()操作符可以按照被观察者发送事件的顺序跳过指定顺序的事件
// 也可以按照被观察者发送事件的时间顺序来跳过指定时间段内发送的事件
Observable.just(1,2,3,4,5,6,7)
.skip(2) //按事件发送的顺序跳过前面指定的2个事件
.skipLast(1) //按事件发送顺序跳过后面指定的1个事件
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer)
throws Exception
{
Log.d(TAG, "accept: 通过skip & skipLast过滤后的数据:" + integer);
}
});
Log.d(TAG, "-------------------------------------------------------------------------------------");
//跳过指定的时间段内被观察者Observable发送的事件序列
Observable.intervalRange(1,7,1,1,TimeUnit.SECONDS)
.skip(1,TimeUnit.SECONDS) //跳过前一秒时间段内的事件
.skipLast(2,TimeUnit.SECONDS) //跳过最后两秒时间段内的事件序列
.subscribe(new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong)
throws Exception
{
Log.d(TAG, "accept: skip & skipLast按照时间过滤后的数据: " + aLong);
}
});
打印结果:
2.4 distinct() / distinceUntilChanged()
//distinct()/ distinctUntilChanged()
Observable.just(1,2,3,4,1,2,3,4,4)
.distinct() //去除重复的元素
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer)
throws Exception
{
Log.d(TAG, "accept: 去除重复元素: " + integer);
}
});
Log.d(TAG, "-------------------------------------------------------------------------");
Observable.fromArray(1,1,2,2,2,3,1,2,3,4,4,4,5,5)
.distinctUntilChanged() //去除连续重复的元素
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer)
throws Exception
{
Log.d(TAG, "accept: 去除连续重复的元素:" + integer);
}
});
打印结果:
2.5 take() / takeLast() 操作符
//take() / takeLast()操作符
//指定只接收被观察者Observable发送的特定数量的事件 可以按照发送顺序 也可以按照时间顺序
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e)
throws Exception
{
e.onNext(1);
e.onNext(2);
e.onNext(3);
e.onNext(4);
}
})
//只订阅被观察者发送的前面的两个事件
//其实被观察者Observable4个事件都发送了 只是通过take操作符
//让观察者Observer只订阅了前面的两个事件
.take(2)
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe: 开始采用subscribe连接 thread = " + Thread.currentThread().getName());
}
@Override
public void onNext(Integer integer) {
Log.d(TAG, "onNext: " + integer + " thread = " + Thread.currentThread().getName());
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError: " + e.getMessage() + " thread = " + Thread.currentThread().getName());
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete: thread = " + Thread.currentThread().getName());
}
});
Log.d(TAG, "--------------------------------------------------------------------------------------");
Observable.just(1,2,3,4,5,6)
//只订阅被观察者Observable发送的后面的两个事件
.takeLast(2)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer)
throws Exception
{
Log.d(TAG, "accept: " + integer);
}
});
Log.d(TAG, "----------------------------------------------------------------");
Observable.intervalRange(1,5,1,1,TimeUnit.SECONDS)
.take(2,TimeUnit.SECONDS)
.subscribe(new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong)
throws Exception
{
Log.d(TAG, "take time :" + aLong);
}
});
Log.d(TAG, "----------------------------------------------------------------");
Observable.intervalRange(1,5,0,1,TimeUnit.SECONDS)
.takeLast(2,TimeUnit.SECONDS)
.subscribe(new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong)
throws Exception
{
Log.d(TAG, "accept: takeLast : " + aLong);
}
});
打印结果:
3.根据指定时间来过滤事件
场景:通过设置指定的时间,仅发送在该时间内的事件
3.1 throttleFirst() / throttleLast()
安卓中常见的应用场景比如:防止某段时间内按钮连续点击多次,造成多次事件的响应即功能防抖
//throttleFirst()/ throttleLast()
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e)
throws Exception
{
e.onNext(1);
SystemClock.sleep(200);
e.onNext(2);
SystemClock.sleep(200);
e.onNext(3);
SystemClock.sleep(200);
e.onNext(4);
SystemClock.sleep(200);
e.onNext(5);
SystemClock.sleep(200);
e.onNext(6);
SystemClock.sleep(200);
e.onNext(7);
SystemClock.sleep(200);
e.onNext(8);
SystemClock.sleep(200);
e.onNext(9);
SystemClock.sleep(200);
e.onNext(10);
SystemClock.sleep(200);
}
})
//只接收每一秒内的第一次发送的事件
// .throttleFirst(1,TimeUnit.SECONDS)
//只接收每300毫秒内的最后一次发送的事件
.throttleLast(300,TimeUnit.MILLISECONDS)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer)
throws Exception
{
Log.d(TAG, "throttle : " + integer);
}
});
打印结果:
throttleFirst(1,TimeUnit.SECONDS)
throttleLast(300,TimeUnit.MILLISECONDS)
3.2 sample()
//sample()操作符
//sample操作符和我们的throttleLast()操作符一致
//就是订阅某个时间段内的被观察者Observable发送的最后一个事件
Observable.intervalRange(1,10,200,200,TimeUnit.MILLISECONDS)
.sample(300,TimeUnit.MILLISECONDS)
.subscribe(new Consumer<Long>() {
@Override
public void accept(@NonNull Long aLong)
throws Exception
{
Log.d(TAG, "sample 采样 :" + aLong);
}
});
打印结果:
3.3 throttleWithTimeout() / debounce()
//throttleWithTimeout()/ debounce()
//被观察者Observable发送数据事件时若相邻2次事件的发送时间间隔小于指定的时间间隔
//则前一次事件会被丢弃,而如果相邻2次事件发送的时间间隔大于指定的时间间隔则会发送后一次的事件
//注意:debounce()操作符会会接着最后一项数据发射原始Observable的onCompleted通知,即使这个通知发生在你指定的时间窗口内(从最后一项数据的发射算起)
//也就是说,onCompleted通知不会触发限流。
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
// 隔断事件发送时间
e.onNext(1);
Thread.sleep(500);
e.onNext(2); // 1和2之间的间隔小于指定时间1s,所以前1次数据(1)会被抛弃,2会被保留
Thread.sleep(1500); // 因为2和3之间的间隔大于指定时间1s,所以之前被保留的2事件将发出
e.onNext(3);
Thread.sleep(1500); // 因为3和4之间的间隔大于指定时间1s,所以3事件将发出
e.onNext(4);
Thread.sleep(1000); // 因为4和5之间的间隔等于指定时间1s(并没有大于1s),所以前1次数据(4)会被抛弃,5会被保留
e.onNext(5);
Thread.sleep(500); // 因为5和6之间的间隔小于指定时间1s,所以前1次数据(5)会被抛弃,6会被保留
e.onNext(6);
// Thread.sleep(1500); // 因为6和Complete事件之间的间隔大于指定时间1s,所以之前被保留的6事件将发出
Thread.sleep(500);
e.onComplete();
}
})
//.throttleWithTimeout(1, TimeUnit.SECONDS)//每1秒中采用数据
.debounce(1,TimeUnit.SECONDS)
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.d(TAG, "接收到了事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "对Error事件作出响应");
}
@Override
public void onComplete() {
Log.d(TAG, "对Complete事件作出响应");
}
});
打印结果:
4.根据指定的事件位置来过滤事件
需求场景:通过设置指定的位置,来过滤改位置的事件
4.1 firstElement()/ lastElement()
//firstElement() / lastElement()操作符
//后去第一个或者最后一个位置上的事件
Observable.just(1,2,3,4,5,6)
.firstElement()
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer)
throws Exception
{
Log.d(TAG, "获取指定的第一个位置的事件: "+ integer);
}
});
Log.d(TAG, "-----------------------------------------------");
Observable.just(1,3,4,5)
.lastElement()
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer)
throws Exception
{
Log.d(TAG, "获取最后一个位置上的事件: "+ integer);
}
});
打印结果:
4.2 elementAt()
//elementAt()操作符
//获取指定位置上的事件
Observable.just(1,2,4,5,6,2,5)
//获取第2个位置上的事件
//注意索引是从0开始的
.elementAt(2)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer)
throws Exception
{
Log.d(TAG, "elmentAt : " + integer);
}
});
Log.d(TAG, "--------------------------------------------------------");
Observable.just(1,2,3)
//获取第5个位置上的的事件
//允许超过事件序列的索引 如果超出可以给定一个预设值
//如果超出范围没有设定预设值的话 则不会进行响应也不会报错
.elementAt(5,100)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer)
throws Exception
{
Log.d(TAG, "elememtAt default: " + integer);
}
});
打印结果:
4.3 elementAtError()
//elementAtError()操作符
//elementAtError()和ElementAt()的区别是elementAtError()当超出事件序列的索引时
//elementAtError()会抛出异常
ObservableError.just(1,2,4,5)
.elementAtOrError(10)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer)
throws Exception
{
Log.d(TAG, "accept: "+ integer);
}
});
打印结果:
ignoreElements()操作符:
//过滤操作符之ignoreElements()
//ignoreElements()操作符会抑制源Observable发射的所有数据只允许
//源Observable的终止通知(onComplete onError)事件通过,其返回的是一个Completable类型
// Observable.just(1,2,3) //有3个next事件和1个complete事件但是只响应complete事件
Observable.error(new Exception("ignoreElements() "))
.ignoreElements()
.subscribe(new CompletableObserver() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onComplete() {
Log.d(TAG, "ignoreElements() 响应 complete事件");
}
@Override
public void onError(@NonNull Throwable e) {
Log.d(TAG, "ignoreElements() 响应 error事件");
}
});
打印结果: