文章导航
RxJava常用操作符
RxJava常用操作符
1.创建操作符
- create():创建最简单的事件流
- from():创建事件流,可发送不同类型的数据流
- just():创建事件流,可发送多个参数的数据流
- defer():创建事件流,可缓存可激活事件流
- range():创建事件流,可发送范围内的数据流
- interval():创建延时重复的事件流
- repeat():创建可重复次数的事件流
- timer():创建一次延时的事件流
补充:interval()、timer()、delay()的区别
- interval():用于创建事件流,周期性重复发送
- timer():用于创建事件流,延时发送一次
- delay():用于事件流中,可以延时某次事件流的发送
1.1 create
create在之前的文章中就有使用,最原生的创建Observable的方式,onNext/onComplete/onError可完全自由控制。
Observable最原始的创建方式,创建出一个最简单的事件流,可以使用发射器发射特定的数据类型
public static void main(String[] args) {
Observable
.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(@NonNull ObservableEmitter<Integer> e) throws Exception {
for (int i = 1; i < 5; i++) {
e.onNext(i);
}
e.onComplete();
}
})
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println("onNext=" + integer);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
}
}, new Action() {
@Override
public void run() throws Exception {
System.out.println("onComplete");
}
});
}
1.2 from
fromArray方法参数为可变长参数,因此既可传数组,也可传多个参数
String[] strings = {
"a", "b", "c"};
Observable.fromArray(strings);
Observable.fromArray("a", "b", "c");
Observable.fromArray(1, 2, 3, 4);
fromIterable方法参数为实现Iterable接口的类,一般为JDK中的List/Map/Set等集合类
String[] strings = {
"aa12", "bb34", "cc56"};
List<String> listString = Arrays.asList(strings);
Observable.fromIterable(listString);
1.3 just
just重载了多个参数数量不同的方法,最大可带10个参数,just同样是调用的fromArray方法;
public static void main(String[] args) {
Observable.just(1, 2, 3, 4, 5)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println("onNext=" + integer);
}
});
}
1.4 defer
defer与just的区别是,just是直接将发射当前的数据流,而defer会等到订阅的时候,才会去执行它的call()回调,再去发射当前的数据流。复杂点的理解就是:defer操作符是将一组数据流在原有的事件流基础上缓存一个新的事件流,直到有人订阅的时候,才会创建它缓存的事件流
i = 10;
Observable<Object> defer = Observable.defer(new Callable<ObservableSource<?>>() {
@Override
public ObservableSource<?> call() throws Exception {
//缓存新的事件流
return Observable.just(i);
}
});
defer.subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
System.out.println("onNext=" + (int) o);
}
});
//修改发射的数据
i = 20;
defer.subscribe(new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
System.out.println("onNext=" + (int) o);
}
});
输出
onNext=10
onNext=20
1.5 range
range操作符发射一个范围内的有序整数数据流,你可以指定范围的起始和长度
public static void main(String[] args) {
Observable.range(10, 4)
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println("onNext=" + integer);
}
});
}
//发送从10开始的整数,发送4个(发到13)
Observable.range(10, 4);
//发送从10开始的长整型数,发送6个(发到15)
Observable.rangeLong(10, 6);
1.6 interval
interval用于定时发送
//每3秒发个自增整数
Observable.interval(3, TimeUnit.SECONDS);
//初始延时1秒,每3秒发一个自增整数
Observable.interval(1, 3, TimeUnit.SECONDS);
//初始延时2秒,后每1秒发一个从10开始的整数,发5个(发到14)停止
Observable.intervalRange(10, 5, 2, 1, TimeUnit.SECONDS);
1.7 repeat
repeat操作符可以重复发送指定次数的某个事件流,repeat操作符默认在trampoline调度器上执行,repeat默认重复次数为Long.MAX_VALUE,可使用重载方法指定次数以及使用repeatUntil指定条件
//一直重复
Observable.fromArray(1, 2, 3, 4).repeat();
//重复发送5次
Observable.fromArray(1, 2, 3, 4).repeat(5);
//重复发送直到符合条件时停止重复
Observable.fromArray(1, 2, 3, 4).repeatUntil(new BooleanSupplier() {
@Override
public boolean getAsBoolean() throws Exception {
//自定判断条件,为true即可停止,默认为false
return false;
}
});
1.8 timer
timer用于延时发送
//延时3秒后,发送一个整数0
Observable.timer(3, TimeUnit.SECONDS);
2.转换操作符
- map():对数据流的类型进行转换
- flatMap():对数据流的类型进行包装成另一个数据流
- scan():对上一轮处理过后的数据流进行函数处理
- groupBy():对所有的数据流进行分组
- buffer():缓存发射的数据流到一定数量,随后发射出数据流集合
- window():缓存发射的数据流到一定数量,随后发射出新的事件流
2.1 map
map利用Function将T转为R
Observable.just("1", "2", "3").map(new Function<String, Integer>() {
@Override
public Integer apply(String s) throws Exception {
return Integer.valueOf(s) * 10;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println(integer);
}
});
2.2 flatMap/concatMap
flatMap操作符将数据流进行类型转换,然后将新的数据流传递给新的事件流进行分发,这里通过模拟请求登录的延时操作进行说明
public void flatMap() {
Observable.just(new UserParams("hensen", "123456")).flatMap(new Function<UserParams, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(UserParams userParams) throws Exception {
return Observable.just(userParams.username + "登录成功").delay(2, TimeUnit.SECONDS);
}
}).subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println(s);
}
});
}
public static class UserParams {
public UserParams(String username, String password) {
this.username = username;
this.password = password;
}
public String username;
public String password;
}
输出
hensen登录成功
concatMap与flatMap的区别
-
concatMap是有序的
-
flatMap是乱序的
2.3 scan
scan操作符会对发射的数据和上一轮发射的数据进行函数处理,并返回的数据供下一轮使用,持续这个过程来产生剩余的数据流。其应用场景有简单的累加计算,判断所有数据的最小值等
public static void main(String[] args) {
Observable.just(8, 2, 13, 1, 15).scan(new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(Integer integer, Integer integer2) throws Exception {
return integer < integer2 ? integer : integer2;
}
})
.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer item) throws Exception {
System.out.println("onNext=" + item);
}
});
}
输出
onNext=8
onNext=2
onNext=2
onNext=1
onNext=1
2.4 groupBy
groupBy操作符可以将发射出来的数据项进行分组,并将分组后的数据项保存在具有key-value映射的事件流中。groupBy具体的分组规则由groupBy操作符传递进来的函数参数Function所决定的,它可以将key和value按照Function的返回值进行分组,返回一个具有分组规则的事件流GroupedObservable,注意这里分组出来的事件流是按照原始事件流的顺序输出的,我们可以通过sorted()对数据项进行排序,然后输出有序的数据流。
public static void main(String[] args) {
Observable.just("java", "c++", "c", "c#", "javaScript", "Android")
.groupBy(new Function<String, Character>() {
@Override
public Character apply(String s) throws Exception {
return s.charAt(0);//按首字母分组
}
})
.subscribe(new Consumer<GroupedObservable<Character, String>>() {
@Override
public void accept(final GroupedObservable<Character, String> characterStringGroupedObservable) throws Exception {
//排序后,直接订阅输出key和value
characterStringGroupedObservable.sorted().subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
System.out.println("onNext= key:" + characterStringGroupedObservable.getKey() + " value:" + s);
}
});
}
});
}
输出
onNext= key:A value:Android
onNext= key:c value:c
onNext= key:c value:c#
onNext= key:c value:c++
onNext= key:j value:java
onNext= key:j value:javaScript
2.5 buffer
buffer操作符可以将发射出来的数据流,在给定的缓存池中进行缓存,当缓存池中的数据项溢满时,则将缓存池的数据项进行输出,重复上述过程,直到将发射出来的数据全部发射出去。如果发射出来的数据不够缓存池的大小,则按照当前发射出来的数量进行输出。如果对buffer操作符设置了skip参数,则buffer每次缓存池溢满时,会跳过指定的skip数据项,然后再进行缓存和输出。
Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9)
.buffer(5).subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> integers) throws Exception {
System.out.println("onNext=" + integers.toString());
}
});
输出
onNext=[1, 2, 3, 4, 5]
onNext=[6, 7, 8, 9]
2.6 window
window操作符和buffer操作符在功能上实现的效果是一样的,但window操作符最大区别在于同样是缓存一定数量的数据项,window操作符最终发射出来的是新的事件流integerObservable,而buffer操作符发射出来的是新的数据流,也就是说,window操作符发射出来新的事件流中的数据项,还可以经过Rxjava其他操作符进行处理。
public static void main(String[] args) {
Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9)
.window(2, 1).subscribe(new Consumer<Observable<Integer>>() {
@Override
public void accept(Observable<Integer> integerObservable) throws Exception {
integerObservable.subscribe(new Consumer<Integer>() {
@Override
public void accept(Integer integer) throws Exception {
System.out.println("onNext=" + integer);
}
});
}
});
}
输出
onNext=1
onNext=2
onNext=2
onNext=3
onNext=3
onNext=4
onNext=4
onNext=5
onNext=5
onNext=6
onNext=6
onNext=7
onNext=7
onNext=8
onNext=8
onNext=9
onNext=9
3.过滤操作符
- debounce():事件流只发射规定范围时间内的数据项
- distinct():事件流只发射不重复的数据项
- elementAt():事件流只发射第N个数据项
- filter():事件流只发射符合规定函数的数据项
- fir