前言
本文基于Rxjava2,与Rxjava略有不同
1,map()
描述:对原始Observable发射的每一项数据应用一个你选择的函数,然后返回一个发射这些结果的Observable
官方示意图:
示例:
Observable.just(1, 2, 3, 4, 5)
.map(new Function<Integer, String>() {
@Override
public String apply(Integer integer) throws Exception {
return "第" + integer + "变";
}
})
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.i(TAG, "onSubscribe");
}
@Override
public void onNext(String value) {
Log.i(TAG, "onNext,value:" + value);
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onError");
}
@Override
public void onComplete() {
Log.i(TAG, "onComplete");
}
});
输出:
2,flatMap()
描述:使用一个指定的函数对原始
Observable
发射的每一项数据执行变换操作,这个函数返回一个本身也发射数据的Observable
,然后FlatMap
的作用就是合并这些Observables
发射的数据,最后将合并后的结果当做它自己的数据序列发射。官方示意图:
注意:此合并操作是无序的,即不保证合并后发射的顺序与原始顺序相同。如要保证顺序选择使用
concatMap()
。如果任何一个通过这个flatMap操作产生的单独的Observable调用onError异常终止了,这个Observable自身会立即调用onError并终止示例:
Observable.just(1, 2, 3, 4)
.flatMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
//这里把每个事件拆分成三个子事件,一一进行发送
List<String> list = new ArrayList<>();
for (int i1 = 0; i1 < 3; i1++) {
list.add("第" + integer + "个事件的第" + i1 + "个子事件");
}
return Observable.fromIterable(list);
}
})
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.i(TAG,"onSubscribe");
}
@Override
public void onNext(String s) {
Log.i(TAG,"onNext,value:"+s);
}
@Override
public void onError(Throwable e) {
Log.i(TAG,"onError");
}
@Override
public void onComplete() {
Log.i(TAG,"onComplete");
}
});
输出:
重载:
flatMap(Func1,int)
:第二个参数设置flatMap
从原来的Observable
映射Observables
的最大同时订阅数。当达到这个限制时,它会等待其中一个终止然后再订阅另一个flatMap(Func1,Func1,Func0)
:为原始Observable的每一项数据和每一个通知创建一个新的Observable(并对数据平坦化)flatMap(Func1,Func1,Func0,int)
:同上,增加最大同时订阅数
应用:此操作符与
concatMap
一样通常用作数据平坦化。例如:有一个学生类集合,每个学生有各个科目的成绩,需求是打印每个学生的各科成绩。通常我们是如此实现:
List<StudentBean> students = new ArrayList<>();
//...省略添加学生数据
Observable.fromIterable(students)
.subscribe(new Consumer<StudentBean>() {
@Override
public void accept(StudentBean studentBean) throws Exception {
List<StudentBean.Subject> grades = studentBean.getGrade();
for (int i1 = 0; i1 < grades.size(); i1++) {
Log.i(TAG, "name:" + grades.get(i1).getSubjectName() + "score:" + grades.get(i1).getScore());
}
}
});
这样可以实现,但是如果我不想在观察者中使用for循环,而是直接传入Subject成绩对象怎么办呢?这一点很重要,因为后续有可能需要对每个Subject对象进行操作。这时候flatMap()
的数据平坦化作用就体现出来了。改造如下:
List<StudentBean> students = new ArrayList<>();
//...省略添加学生数据
Observable.fromIterable(students)
.flatMap(new Function<StudentBean, ObservableSource<StudentBean.Subject>>() {
@Override
public ObservableSource<StudentBean.Subject> apply(StudentBean studentBean) throws Exception {
return Observable.fromIterable(studentBean.getGrade());
}
})
.subscribe(new Consumer<StudentBean.Subject>() {
@Override
public void accept(StudentBean.Subject subject) throws Exception {
Log.i(TAG, "name:" + subject.getSubjectName() + "score:" + subject.getScore());
}
});
很优美对不对?此外,我们可以使用flatMap()
来中进行嵌套异步操作,或者嵌套的网络访问,一条链走到底。
3,flatMapIterable()
描述:
flatMapIterable
与flatMap
在处理方式上相同的。唯一不同的是,flatMap
是把一个Observable
转换成多个Observables
。每一个Observable
,最后需要返回一个Observable
。而flatMapIterable
在将一个Observable
转换成多个Observables
后,每一个Observable
只能返回一个Iterable
,而不是Observable
。(Iterable
是个接口,Collection
实现了此接口,也就是所有的list、set都是它的子类)官方示意图:
示例:
Observable.just(1, 2, 3)
.flatMapIterable(new Function<Integer, Iterable<String>>() {
@Override
public Iterable<String> apply(Integer integer) throws Exception {
return Arrays.asList("第一个元素" + integer, "第二个元素" + integer);
}
})
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i(TAG, "accept:" + s);
}
});
输出:
重载:
flatMapIterable(Func1,Func2)
4,concatMap()
描述:它类似于最简单版本的
flatMap
,但是它按次序连接而不是合并那些生成的Observables,然后产生自己的数据序列。与flatMap
用法一模一样。官方示意图:
5,switchMap()
描述:它和
flatMap
很像,除了一点:当原始Observable
发射一个新的数据(Observable)
时,它将取消订阅并停止监视产生这之前那个数据的Observable
,只监视当前这一个。如果是在同一线程中,第二个数据项来临时第一个已经完成了,此操作符不会产生效果。当在多线程中,第二个数据项来临后如果第一个没有完成,将会取消订阅并停止监视前一个Observable
。官方示意图:
示例:
Observable.just(1, 2, 3)
.switchMap(new Function<Integer, ObservableSource<String>>() {
@Override
public ObservableSource<String> apply(Integer integer) throws Exception {
List<String> list = new ArrayList<>();
for (int i1 = 0; i1 < 2; i1++) {
list.add("第" + integer + "个事件的第" + i1 + "个子事件");
}
//多线程中订阅
return Observable.fromIterable(list).subscribeOn(Schedulers.newThread());
}
})
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.i(TAG, "onSubscribe");
}
@Override
public void onNext(String s) {
Log.i(TAG, "onNext,value:" + s);
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onError");
}
@Override
public void onComplete() {
Log.i(TAG, "onComplete");
}
});
输出:
没有第一个和第二个事件,是因为都被后一个事件来临后给取消了。
6,split()
描述:在特殊的StringObservable类(默认没有包含在RxJava中)中还有一个split操作符。它将一个发射字符串的Observable转换为另一个发射字符串的Observable,只不过,后者将原始的数据序列当做一个数据流,使用一个正则表达式边界分割它们,然后合并发射分割的结果。
官方示意图:
7,buffer()
描述:将一个
Observable
变换为另一个,原来的Observable
正常发射数据,变换产生的Observable
发射这些数据的缓存集合。注意:如果原来的
Observable
发射了一个onError通知,Buffer
会立即传递这个通知,而不是首先发射缓存的数据,即使在这之前缓存中包含了原始Observable
发射的数据。官方示意图:
示例:
Observable.just(1, 2, 3, 4, 5)
.buffer(2)
.subscribe(new Observer<List<Integer>>() {
@Override
public void onSubscribe(Disposable d) {
Log.i(TAG, "onSubscribe");
}
@Override
public void onNext(List<Integer> integers) {
Log.i(TAG, "onNext:缓存集合长度:" + integers.size());
for (int i1 = 0; i1 < integers.size(); i1++) {
Log.i(TAG, "onNext:集合item:" + integers.get(i1));
}
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "onError");
}
@Override
public void onComplete() {
Log.i(TAG, "onComplete");
}
});
输出:
重载:
buffer(count, skip)
描述:从原始
Observable
的第一项数据开始创建新的缓存,此后每当收到skip
项数据,用count
项数据填充缓存:开头的一项和后续的count-1
项,它以列表(List)的形式发射缓存,取决于count
和skip
的值,这些缓存可能会有重叠部分(比如skip < count时),也可能会有间隙(比如skip > count时)。示意图:
buffer(bufferClosingSelector)
描述:当它订阅原来的
Observable
时,buffer(bufferClosingSelector)
开始将数据收集到一个List,然后它调用bufferClosingSelector
生成第二个Observable
,当第二个Observable
发射一个TClosing
时,buffer
发射当前的List
,然后重复这个过程:开始组装一个新的List
,然后调用bufferClosingSelector
创建一个新的Observable
并监视它。它会一直这样做直到原来的Observable
执行完成。示意图:
buffer(boundary)
描述:
buffer(boundary)
监视一个名叫boundary
的Observable
,每当这个Observable
发射了一个值,它就创建一个新的List
开始收集来自原始Observable
的数据并发射原来的List
。示意图:
buffer(bufferOpenings, bufferClosingSelector)
描述:
buffer(bufferOpenings, bufferClosingSelector)
监视这个叫bufferOpenings
的Observable
(它发射BufferOpening对象),每当bufferOpenings
发射了一个数据时,它就创建一个新的List
开始收集原始Observable
的数据,并将bufferOpenings
传递给closingSelector
函数。这个函数返回一个Observable
。buffer
监视这个Observable
,当它检测到一个来自这个Observable
的数据时,就关闭List
并且发射它自己的数据(之前的那个List)。示意图:
buffer(timespan, unit[, scheduler])
描述:
buffer(timespan, unit)
定期以List
的形式发射新的数据,每个时间段,收集来自原始Observable
的数据(从前面一个数据包裹之后,或者如果是第一个数据包裹,从有观察者订阅原来的Observale之后开始)。还有另一个版本的buffer
接受一个Scheduler
参数,默认情况下会使用computation
调度器。示意图:
buffer(timespan, unit, count[, scheduler])
描述:每当收到来自原始
Observable
的count
项数据,或者每过了一段指定的时间后,buffer(timespan, unit, count)
就以List
的形式发射这期间的数据,即使数据项少于count
项。还有另一个版本的buffer
接受一个Scheduler
参数,默认情况下会使用computation
调度器。示意图:
buffer(timespan, timeshift, unit[, scheduler])
描述:
buffer(timespan, timeshift, unit)
在每一个timeshift
时期内都创建一个新的List
,然后用原始Observable
发射的每一项数据填充这个列表(在把这个List当做自己的数据发射前,从创建时开始,直到过了timespan这么长的时间)。如果timespan
长于timeshift
,它发射的数据包将会重叠,因此可能包含重复的数据项。示意图:
8,scan()
描述:
Scan
操作符对原始Observable
发射的第一项数据应用一个函数,然后将那个函数的结果作为自己的第一项数据发射。它将函数的结果同第二项数据一起填充给这个函数来产生它自己的第二项数据。它持续进行这个过程来产生剩余的数据序列。示意图:
示例:
Observable.just(1, 2, 3, 4, 5)
.scan(new Func2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer sum, Integer item) {
return sum + item;
}
}).subscribe(new Subscriber<Integer>() {
@Override
public void onNext(Integer item) {
System.out.println("Next: " + item);
}
@Override
public void onError(Throwable error) {
System.err.println("Error: " + error.getMessage());
}
@Override
public void onCompleted() {
System.out.println("Sequence complete.");
}
});
输出:
Next: 1 Next: 3 Next: 6 Next: 10 Next: 15 Sequence complete.
重载:
scan(R,Func2)
- 说明:你可以传递一个种子值给累加器函数的第一次调用(Observable发射的第一项数据)。如果你使用这个操作符,scan将发射种子值作为自己的第一项数据。注意:传递null作为种子值与不传递是不同的,null种子值是合法的。