本章讲的是操作符,有rxjava1经验的同志们,请继续右转。不对。。。可能都不用继续往下看。。
操作符
什么叫操作符,如果按照直接的个人理解,我会解释给你听,他是将你的Observable或者是Flowable转换成另外一种Observable或者是另外一种Flowable
用我们的上下游分析法,我们把操作符称为中游的拦截者。
我们用伪代码来解释的话就是这样的:
Flowable/Observable.操作符 = Flowable/Observable
而rxjava2的操作符基本跟rxjava1没有什么太大的出入。我们先来看一个最最基础的
-
map
不要把这个map跟你理解的map混淆起来,他不是你理解的map
```
public final
ObjectHelper.requireNonNull(mapper, "mapper is null");
return RxJavaPlugins.onAssembly(new FlowableMap
}
我们不要去管这个方法是干什么的,从这个方法的传参和返回类型,就可以基本知道他是干什么的。它是把Flowable变成了Flowable。
这个拦截者在中游拦截到了上游扔下来的一个包袱,打开,把里面的东西T,换成了东西R,扔到下游。
* ####flatMap
```
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Observable flatMap(Function super T, ? extends ObservableSource extends R>> mapper) {
return flatMap(mapper, false);
}
上面的map方法直接是最最纯粹的类型转换,而这个方法则允许你讲获取到类型T,进行再次操作,最后返回一个经过你重新包装的Observable。
这个拦截者比map还要胡来,直接在中游拦截到了上游的包袱,直接整个拿掉,并且把自己的包袱扔到了下游。
-
还有什么map
由于一下子有了两个map让我们不禁好奇是不是还有一些map,我们在Observable类中,搜索了一下带有map的方法,发现还有两个,一个是concatMap,一个是switchMap。
我们尝试着在subscribe中发送多个onNext请求,然后对这三种map做一一的处理,并在在最后的subscribe中做接受并打印结果
Observable.create(new ObservableOnSubscribe() {
@Override
public void subscribe(ObservableEmitter emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
}
}).flatMap(new Function>() {
@Override
public ObservableSource apply(Integer integer) throws Exception {
final List list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
list.add("I am value " + integer);
}
return Observable.fromIterable(list).delay(10,TimeUnit.MILLISECONDS);
}
}).subscribe(new Consumer() {
@Override
public void accept(String s) throws Exception {
Log.d(TAG, s);
}
});
最终打印出来的结果可以看到concatMap是按照顺序的,flatMap和switchMap都是无序。
那flatMap和switchMap有什么不一样呢,我们看到switchMap方法上有这么一段备注:
emitting the items emitted by the most recently emitted
of these ObservableSources
说明他接收的是最近的一个数据,那么具体最近的定义事多少呢,我们先不去看具体的相应时间差是多少,我们在map方法中对delay稍作修改
int delay = 200;
if (integer > 1)
delay = 180;
return Observable.fromIterable(list).delay(delay, TimeUnit.MILLISECONDS);
对大于1的延迟改为180毫秒,否则延迟是200毫秒,你会发现switchMap只能收到3。
那么我们略微的总结一下,如果你对顺序要求比较高的你就使用concatMap;如果你对顺序是没有要求的,但是不希望错过任何一个请求的,那你就使用flatMap;如果你对同一时间内的请求只需要一个(感觉这种情况会比较少),那就使用switchMap。
-
zip
很有可能跟你想的是一样的,zip我们都知道是干嘛用的,那么在这边当操作符用的话,你想一想是干嘛用的,如果用我们的上下游分析法来分析的话,这一回中游的拦截者做了什么。
我们在`Observable`类中搜索zip的方法,发现重载了好多, 我们看到有很多种传参
public static Observable zip(
ObservableSource extends T1> source1, ObservableSource extends T2> source2,
BiFunction super T1, ? super T2, ? extends R> zipper) {
return zipArray(Functions.toFunction(zipper), false, bufferSize(), source1, source2);
}
我们就来看一下这个方法,传入两个Observable,传出一个Observable。
这一回中游的拦截者做的事情是把上游上两个不同的扔东西的人的东西捆绑在一块儿再往下游扔。
读者可以自行的定义两个Observable,并且调用
Observable.zip(observable1, observable2, new ...)
你做了几番尝试之后,你会通过log发现如下的一些结果
* zip只会打包onNext方法
* 打包渠道中只要有一个渠道触发了onComplete方法,那么就会停止继续打包。
-
zip有什么用
我们平时有没有过一种情况,有两个网络请求,我们需要等着两个网络请求都收到结果之后再做下一步的操作。
那么在没有使用rxjava之前我们是这样做的:
```
httpRequest1.request();
httpRequest2.request();
onRequest1(){
request1 = true;
goNext();
}
onRequest2(){
request2 = true;
goNext();
}
goNext(){
if(request1 && request2){
//TODO
}
}
我就问你,难不难受。。。。
如果使用zip操作符,你根本就不用去管这两个东西谁先来谁后来什么的,只要你出发了onNext那我就可以直接catch到你,并且把你打包了。由于我们使用的网络请求的例子。你如果自己去通过HttpUrlConnection实现,这里推荐使用Retrofit,直接继承了Rxjava,可谓是当前最好用的网络请求框架。
Observable observable1 =
api.getRespones1(new Request1()).subscribeOn(Schedulers.io());
Observable observable2 =
api.getRespones2(new Request2()).subscribeOn(Schedulers.io());
Observable.zip(observable1, observable2,
new BiFunction() {
@Override
public YourObject apply(Response1 baseInfo,
Response2 extraInfo) throws Exception {
//do something
return new YourObject(baseInfo, extraInfo);
}
}).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer() {
@Override
public void accept(YourObject userInfo) throws Exception {
//do something;
}
});
而具体的Retrofit的使用姿势,大家可以先去查阅相应的文档,我不确定之后会不会再来写一下。
* ##filter
这个操作符的作用,就跟他字面意思一样,筛选。
我们直接用了看看
```
Flowable flowable = Flowable.create(new FlowableOnSubscribe() {
@Override
public void subscribe(FlowableEmitter e) throws Exception {
for(int i = 0; i < 400; i++){
Thread.sleep(100);
Log.e("subscribe", "i : " + i);
e.onNext(i);
}
}
}, BackpressureStrategy.ERROR).filter(new Predicate() {
@Override
public boolean test(@NonNull Integer integer) throws Exception {
return integer > 300;
}
});
然后你把这个flowable订阅一下,你会发现他只会输出大于300的onNext,也就是说会把你的onNext携带的请求对象进行筛选,只取你需要的请求。
-
sample
取样操作符
public final Flowable sample(long period, TimeUnit unit) {
return sample(period, unit, Schedulers.computation());
}
每隔一段时间,取一个样本。当然他还有一些重载的方法,都比较简单,再次不一一列出。
-
compose
这个厉害了,我们平时在书写我们的Flowable或者是Observable的时候,一直都会喜欢做一些额外的操作,比如说observerOn,比如说subscribeOn。
为了不每一次都这么来On一下。我们是否想一想通过什么方式把这些东西抽出来,对其进行重用。
这个时候我们需要使用compose操作符
```
observable2.compose(new ObservableTransformer
@Override
public ObservableSource
return upstream.subscribeOn(Schedulers.io());;
}
});
flowable.compose(new FlowableTransformer
@Override
public Publisher
return upstream.subscribeOn(Schedulers.io());
}
})
我们可以看到observable和flowable的compose方法的传参有所不同,rxjava2,特地为两者各自准备了他们自己的Transformer(估计是为了考虑到背压的问题),因此我们拿一个具体的Transformer出来讲:
public interface ObservableTransformer
/**
* Applies a function to the upstream Observable and returns an ObservableSource with
* optionally different element type.
* @param upstream the upstream Observable instance
* @return the transformed ObservableSource instance
*/
ObservableSource
}
我们只需要虚自定义一个我们自己的transformer实现ObservableTransformer接口即可。
* 和flatMap有什么不一样么
一个是吧Observable转成Observable,一个是把T转成Observable。
也就是说compose操作符是把整个的上游给换了一个新的Observable,所有的都按照我的来;而flatMap是你来一个请求我给你包装成一个新的Observable,细一看区别还是很明显的。
* ##后续操作符留坑
TBC...
-------
##电梯
[抱着陌生的态度再看Rxjava(一)](http://www.jianshu.com/p/fbfdd6fa6154)
[抱着陌生的态度再看Rxjava(二)](http://www.jianshu.com/p/96df60fd35c6)
[抱着陌生的态度再看Rxjava(四)](http://www.jianshu.com/p/de8af3fadede)