这篇章主要介绍Rxjava的变换操作符
目录
Buffer
Buffer
操作符将一个Observable变换为另一个,原来的Observable正常发射数据,变换产生的Observable发射这些数据的缓存集合。这是中文帮助文档的解释,先看代码,我再按自己的了解描述一次
Observable.just(1,2,3,4,5,6,7,8,9).buffer(3).subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> integers) throws Exception {
System.out.println("--size:" + integers.size());
for (int integer : integers) {
System.out.println("--value:" + integer);
}
}
});
结果:
--size:3
--value:1
--value:2
--value:3
--size:3
--value:4
--value:5
--value:6
--size:3
--value:7
--value:8
--value:9
buffer里面传入3,其实就是把本来Observable.just创建出来的Observable转换成一个新的Observable,而这个新的Observable就是以原数据每三个作为一个列表发射出去而已。
Observable.just(1,2,3,4,5,6,7,8,9).buffer(3, 2).subscribe(new Consumer<List<Integer>>() {
@Override
public void accept(List<Integer> integers) throws Exception {
System.out.println("--size:" + integers.size());
for (int integer : integers) {
System.out.println("--value:" + integer);
}
}
});
结果:
--size:3
--value:1
--value:2
--value:3
--size:3
--value:3
--value:4
--value:5
--size:3
--value:5
--value:6
--value:7
--size:3
--value:7
--value:8
--value:9
--size:1
--value:9
buffer.(3,2),一参为每次发射列表的个数,二参为每次取列表所跳过的个数,如上面结果所示,第一个列表为1,2,3,然后跳过两个,所以第二个列表取到的是3,4,5了。其实上面只传一个参数buffer(3)的写法,就相当于buffer(?,?),?是什么呢,你在评论里回答,这样都回答不出,怎么面对你的列祖列宗。没错答案就是buffer(3,3)。
FlatMap
FlatMap
将一个发射数据的Observable变换为多个Observables,然后将它们发射的数据合并后放进一个单独的Observable。
根据文档说法和下面的图,其实个人理解就是你发射了一组三个数据的,而每个数据经过flatMap的雨露恩泽后,都变成了一个新的Observable,而每个Observable会重新订阅即subscribe你原来Observable本来subscribe的那个家伙(那个observer观察者)。我写完都不知自己在说什么,都说了看代码是最好的。
Observable.just(1,2,3).flatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Throwable {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < integer; i++){
list.add(integer);
}
return Observable.fromIterable(list).map(num -> num+"+");
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable disposable) {
}
@Override
public void onNext(String s) {
System.out.println(s+"*");
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onComplete() {
System.out.println("完成");
}
});
结果:
1+*
2+*
2+*
3+*
3+*
3+*
完成
flatmap产生的每个新的Observable只会调用观察者的onNext,所有完成才会调用onComplete
GroupBy
将一个Observable分拆为一些Observables集合,它们中的每一个发射原始Observable的一个子序列。看代码
String[] strs = {"同调怪兽", "永续魔法", "速攻魔法", "超量怪兽", "仪式怪兽", "反击陷阱", "场地魔法", "永续陷阱"};
Observable.fromArray(strs).groupBy(s -> {
if (s.contains("怪兽")) {
return "怪兽";
}
else if (s.contains("魔法")) {
return "魔法";
}
else {
return "陷阱";
}
}).subscribe(new Observer<GroupedObservable<String, String>>() {
@Override
public void onSubscribe(Disposable disposable) {
}
@Override
public void onNext(GroupedObservable<String, String> groupedObservable) {
groupedObservable.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable disposable) {
}
@Override
public void onNext(String s) {
System.out.println(groupedObservable.getKey() + "组: " + s);
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onComplete() {
System.out.println(groupedObservable.getKey() + "组完成");
}
});
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onComplete() {
System.out.println("全部完成");
}
});
结果:
怪兽组: 同调怪兽
魔法组: 永续魔法
魔法组: 速攻魔法
怪兽组: 超量怪兽
怪兽组: 仪式怪兽
陷阱组: 反击陷阱
魔法组: 场地魔法
陷阱组: 永续陷阱
魔法组完成
怪兽组完成
陷阱组完成
全部完成
groupby后的Observable要订阅放了GroupedObservable<T, E>的观察者observer,T其实就是每一组的key,我上面是根据这样分key的。
if (s.contains("怪兽")) {
return "怪兽";
}
else if (s.contains("魔法")) {
return "魔法";
}
else {
return "陷阱";
}
而E就是跟原来要发射的数据同类型。groupby其实就是把本来的数据,每一个转换成GroupedObservable<T, E>,而这个GroupedObservable也是Observable来的,所以Observable的操作符它都能用。
Map
看代码
Observable.just(1,2,3).map(num -> num+"+").subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Throwable {
System.out.println(s+"*");
}
});
结果:
1+*
2+*
3+*
说白就是,把你本来发射的数据,经过一个函数得到新的值再发射出去。看到map的时候,我一直在想,我写一个函数方法出来,然后把我的数组经过我的函数得到新的数组再扔个just,不是一样的效果吗。或是在onNext的时候得到的数据先经过我写的函数方法,再打印出来,不也是一样吗。
那为啥要有个map操作符。
这就是你跟别人的差距啦。人家用map就可以链式的写法,看起来代码就比较玲珑浮凸,而且可以非常容易看到转换的代码在哪里,都做了什么转换。除了这些,其实我还真没想到用这个map还有什么好地方。
Cast
Person[] people = {new Student("aaa"), new Student("bbb"), new Student("ccc")};
Observable.fromArray(people).cast(Student.class).subscribe(new Consumer<Student>() {
@Override
public void accept(Student student) throws Throwable {
System.out.println(student.getName()+"+");
}
});
结果也不贴出来了,其实很简单这个。不是我不想打字,代码就能解析清楚的事情,写一遍论文干什么。Cast就是把发送的数据强转为另外一个类型,当然上面的Person类要是Student类的父类才行啦。
Scan
Scan
操作符对原始Observable发射的第一项数据应用一个函数,然后将那个函数的结果作为自己的第一项数据发射。它将函数的结果同第二项数据一起填充给这个函数来产生它自己的第二项数据。这个不粘贴给你看,可能有点难理解。
Observable.just(1, 2, 3, 4, 5).scan(new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(Integer sum, Integer item) throws Throwable {
return sum+item;
}
}).subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable disposable) {
}
@Override
public void onNext(Integer s) {
System.out.println(s+"*");
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onComplete() {
System.out.println("完成");
}
});
结果
1*
3*
6*
10*
15*
完成
上面1,3,6,10,15实际要发射给观察者observer的数据。过程就是先发射原数据第一个数据,然后要发射的数据二是根据刚刚发射的数据和数据二进行你写的函数得到的。那要发射的数据三就是刚刚发射的数据和数据三运算得到了罗……。
Window
定期将来自原始Observable的数据分解为一个Observable窗口,发射这些窗口,而不是每次发射一项数据
Observable.just(1,2,3,4,5,6,7,8,9).window(3).subscribe(new Observer<Observable<Integer>>() {
@Override
public void onSubscribe(Disposable disposable) {
}
@Override
public void onNext(Observable<Integer> integerObservable) {
integerObservable.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable disposable) {
}
@Override
public void onNext(Integer integer) {
System.out.println(integer+"*");
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onComplete() {
System.out.println("里面完成");
}
});
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onComplete() {
System.out.println("全部完成");
}
});
结果:
1*
2*
3*
里面完成
4*
5*
6*
里面完成
7*
8*
9*
里面完成
全部完成
上面的代码效果跟buffer(3)效果有点像,buffer是什么?就在上面就在上面,翻上去看一下,再下来。不过就是buffer,是根据原数据分组成几个列表发射给observer。而window即是把原数据分组成一个个Observable。上面的代码你就可以理解为把原数据分成了Observable.just(1,2,3),Observable.just(4,5,6),Observable.just(7,8,9)。如果用window就可以把数据转成Observable,那你有可以为所欲为啦。