Map
操作符的作用是对上游发送的每一个事件应用一个函数,使得每个事件按照函数的逻辑进行变换,通过Map
就可以把上游发送的每一个事件,转换成Object
或者集合.
/**
* map关键词主要是将发送事件通过Map转换成另一种下游所需要的目标类型
*/
public static void MapTest(){
Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter emitter) throws Exception {
Log.e(TAG_OBSERVABLE,"被处理之前的值:1");
emitter.onNext(1);
Log.e(TAG_OBSERVABLE,"被处理之前的值:2");
emitter.onNext(2);
Log.e(TAG_OBSERVABLE,"被处理之前的值:3");
emitter.onNext(3);
}
}).map(new Function() {//在下游接收到事件之前处理,返回一个新的Observable
@Override
public String apply(Integer integer) throws Exception {
return "我被转换成:"+integer;
}
}).subscribe(new Consumer() {
@Override
public void accept(String s) throws Exception {
Log.e(TAG_OBSERVAER,"接收的内容:"+s);
}
});
}
结果:
map
基本作用就是将一个 Observable
通过某种函数关系,转换为另一种 Observable
,上面例子中就是把我们的 Integer
数据变成了 String
类型。从Log日志显而易见。
map
函数调用完毕之后,将返回一个新的Observable
,它的类型为ObservableMap.
使用场景:
网络请求返回结果,可以在map中进行数据解析,转换成需要的数据格式发送给下游,进行UI更新。
FlatMap
上游每发送一个事件, flatMap都将创建一个新的水管, 然后发送转换之后的新的事件, 下游接收到的就是这些新的水管发送的数据. 这里需要注意的是, flatMap并不保证事件的顺序。
concatMap与flatMap的作用几乎一样,只是concatMap结果严格按照上游发送的顺序。
Observable integerObservable = Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter emitter) throws Exception {
Log.e(TAG_OBSERVABLE, "ObservableEmitter:" + Thread.currentThread().getName());
Log.e(TAG_OBSERVABLE, "发射器1被处理之前的值:1");
emitter.onNext(1);
Log.e(TAG_OBSERVABLE, "发射器1被处理之前的值:2");
emitter.onNext(2);
Log.e(TAG_OBSERVABLE, "发射器1被处理之前的值:3");
emitter.onNext(3);
emitter.onComplete();
}
});
integerObservable
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.flatMap(new Function>() {
@Override
public ObservableSource apply(Integer integer) throws Exception {
Log.e(TAG_OBSERVABLE, "apply:" + Thread.currentThread().getName());
List list = new ArrayList<>();
for (int i = 0; i < 2; i++) {
list.add("我的值:" + integer);
}
int delayTime = (int) (1 + Math.random() * 10);
return Observable.fromIterable(list).delay(delayTime, TimeUnit.MILLISECONDS);
}
}).subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.newThread())
.subscribe(new Consumer() {
@Override
public void accept(String s) throws Exception {
Log.e(TAG_OBSERVABLE, "accept:" + Thread.currentThread().getName());
Log.e(TAG_OBSERVAER, "接收到的:" + s);
}
});
结果:
使用场景:
可以用于类似注册成功后返回的数据再调用登录接口获取用户信息,多个接口连接转换。
Zip
zip
专用于合并事件,该合并不是连接(连接操作符后面会说),而是两两配对,也就意味着,最终配对出的 Observable
发射事件数目只和少的那个相同。
/**
* zip关键词主要是将两个事件合并成一个事件提供给下游处理
*/
public static void zipTest(){
Observable integerObservable=Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter emitter) throws Exception {
Log.e(TAG_OBSERVABLE,"被处理之前的值:1");
emitter.onNext(1);
Log.e(TAG_OBSERVABLE,"被处理之前的值:2");
emitter.onNext(2);
Log.e(TAG_OBSERVABLE,"被处理之前的值:3");
emitter.onNext(3);
}
});
Observable stringObservable=Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter emitter) throws Exception {
emitter.onNext("我叫:");
emitter.onNext("我女朋友叫:");
}
});
Observable.zip(integerObservable, stringObservable, new BiFunction() {
@Override
public String apply(Integer integer, String s) throws Exception {
return s+integer;
}
}).subscribe(new Consumer() {
@Override
public void accept(String s) throws Exception {
Log.e(TAG_OBSERVAER,"接收的内容:"+s);
}
});
}
结果:
这种可以用于多个请求合并处理对应的结果.不管事件是怎样的,A1总是跟B1结合,两个事件中的顺序都是按照对应的位置进行的。下游最终接收到的事件个数都是上游中事件数最少的那个被观察者为准。
Concat
单一的把多个发射器连接成一个发射器,由于中间没有其他转换要求每个observable对象的发送事件类型一致,接收到的结果按照注册的优先顺序发送,不管是否在同一线程。
疑问:concat怎么判断该被观察者已经发送完成了,测试发现不是以onComplete()结束为标识?
解答:其实在concat中会存储每个observable对象需要发送的事件个数,从而得知该被观察者是否已经全部发送完毕。
附RxJava操作符全解Demo:一点直达RxJava操作符全解