前言
Rxjava
,由于其基于事件流的链式调用、逻辑简洁 & 使用简单的特点,深受各大 Android
开发者的欢迎。
![Github截图](http://upload-images.jianshu.io/upload_images/944365-d0d78b3b826170ed.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
如果还不了解 RxJava
,请看文章:Android:这是一篇 清晰 & 易懂的Rxjava 入门教程
RxJava
如此受欢迎的原因,在于其提供了丰富 & 功能强大的操作符,几乎能完成所有的功能需求
- 今天,我将为大家详细介绍
RxJava
操作符中最常用的 组合 / 合并操作符,并附带 Retrofit 结合 RxJava的实例Demo教学,希望你们会喜欢。
- 本系列文章主要基于
Rxjava 2.0
- 接下来的时间,我将持续推出
Android
中 Rxjava 2.0
的一系列文章,包括原理、操作符、应用场景、背压等等 ,有兴趣可以继续关注Carson_Ho的安卓开发笔记!!
目录
![示意图](http://upload-images.jianshu.io/upload_images/944365-ff482b5b1d2a097c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
1. 作用
组合 多个被观察者(`Observable`) & 合并需要发送的事件
2. 类型
3. 应用场景 & 对应操作符 介绍
注:在使用RxJava 2
操作符前,记得在项目的Gradle
中添加依赖:
dependencies {
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
compile 'io.reactivex.rxjava2:rxjava:2.0.7'
}
3.1 组合多个被观察者
该类型的操作符的作用 = 组合多个被观察者
concat() / concatArray()
Observable.concat(Observable.just(1, 2, 3),
Observable.just(4, 5, 6),
Observable.just(7, 8, 9),
Observable.just(10, 11, 12))
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.d(TAG, "接收到了事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "对Error事件作出响应");
}
@Override
public void onComplete() {
Log.d(TAG, "对Complete事件作出响应");
}
});
Observable.concatArray(Observable.just(1, 2, 3),
Observable.just(4, 5, 6),
Observable.just(7, 8, 9),
Observable.just(10, 11, 12),
Observable.just(13, 14, 15))
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.d(TAG, "接收到了事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "对Error事件作出响应");
}
@Override
public void onComplete() {
Log.d(TAG, "对Complete事件作出响应");
}
});
![concat()情况](http://upload-images.jianshu.io/upload_images/944365-ad8d11dea3d4abd0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![concatArray()情况](http://upload-images.jianshu.io/upload_images/944365-b4d6ee8caa063675.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
merge() / mergeArray()
Observable.merge(
Observable.intervalRange(0, 3, 1, 1, TimeUnit.SECONDS),
Observable.intervalRange(2, 3, 1, 1, TimeUnit.SECONDS))
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Long value) {
Log.d(TAG, "接收到了事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "对Error事件作出响应");
}
@Override
public void onComplete() {
Log.d(TAG, "对Complete事件作出响应");
}
});
两个被观察者发送事件并行执行,输出结果 = 0,2 -> 1,3 -> 2,4
![33333.gif](http://upload-images.jianshu.io/upload_images/944365-f75b9d25af87f24c.gif?imageMogr2/auto-orient/strip)
concatDelayError() / mergeDelayError()
![示意图](http://upload-images.jianshu.io/upload_images/944365-0a86e8e45f1abb6c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
a. 无使用concatDelayError()的情况
Observable.concat(
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onError(new NullPointerException());
emitter.onComplete();
}
}),
Observable.just(4, 5, 6))
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.d(TAG, "接收到了事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "对Error事件作出响应");
}
@Override
public void onComplete() {
Log.d(TAG, "对Complete事件作出响应");
}
});
测试结果:第1个被观察者发送Error事件后,第2个被观察者则不会继续发送事件
![示意图](http://upload-images.jianshu.io/upload_images/944365-0c907ffaeb2fd449.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
<-- 使用了concatDelayError()的情况 -->
Observable.concatArrayDelayError(
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
emitter.onNext(1);
emitter.onNext(2);
emitter.onNext(3);
emitter.onError(new NullPointerException());
emitter.onComplete();
}
}),
Observable.just(4, 5, 6))
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.d(TAG, "接收到了事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "对Error事件作出响应");
}
@Override
public void onComplete() {
Log.d(TAG, "对Complete事件作出响应");
}
});
测试结果:第1个被观察者的Error事件将在第2个被观察者发送完事件后再继续发送
![示意图](http://upload-images.jianshu.io/upload_images/944365-804c8472fc60eb6a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
mergeDelayError()
操作符同理,此处不作过多演示
3.2 合并多个事件
该类型的操作符主要是对多个被观察者中的事件进行合并处理。
Zip()
![示意图](http://upload-images.jianshu.io/upload_images/944365-3fa4b1fd4f561820.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 特别注意:
- 事件组合方式 = 严格按照原先事件序列 进行对位合并
- 最终合并的事件数量 = 多个被观察者(
Observable
)中数量最少的数量
即如下图
<-- 创建第1个被观察者 -->
Observable<Integer> observable1 = Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
Log.d(TAG, "被观察者1发送了事件1");
emitter.onNext(1);
Thread.sleep(1000);
Log.d(TAG, "被观察者1发送了事件2");
emitter.onNext(2);
Thread.sleep(1000);
Log.d(TAG, "被观察者1发送了事件3");
emitter.onNext(3);
Thread.sleep(1000);
emitter.onComplete();
}
}).subscribeOn(Schedulers.io());
<-- 创建第2个被观察者 -->
Observable<String> observable2 = Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
Log.d(TAG, "被观察者2发送了事件A");
emitter.onNext("A");
Thread.sleep(1000);
Log.d(TAG, "被观察者2发送了事件B");
emitter.onNext("B");
Thread.sleep(1000);
Log.d(TAG, "被观察者2发送了事件C");
emitter.onNext("C");
Thread.sleep(1000);
Log.d(TAG, "被观察者2发送了事件D");
emitter.onNext("D");
Thread.sleep(1000);
emitter.onComplete();
}
}).subscribeOn(Schedulers.newThread());
<-- 使用zip变换操作符进行事件合并 -->
Observable.zip(observable1, observable2, new BiFunction<Integer, String, String>() {
@Override
public String apply(Integer integer, String string) throws Exception {
return integer + string;
}
}).subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
Log.d(TAG, "onSubscribe");
}
@Override
public void onNext(String value) {
Log.d(TAG, "最终接收到的事件 = " + value);
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError");
}
@Override
public void onComplete() {
Log.d(TAG, "onComplete");
}
});
![示意图](http://upload-images.jianshu.io/upload_images/944365-8986cf9178060877.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 特别注意:
- 尽管被观察者2的事件
D
没有事件与其合并,但还是会继续发送
- 若在被观察者1 & 被观察者2的事件序列最后发送
onComplete()
事件,则被观察者2的事件D也不会发送,测试结果如下
![示意图](http://upload-images.jianshu.io/upload_images/944365-7b241e653250b906.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 因为
Zip()
操作符较为复杂 & 难理解,此处将用1张图总结
![示意图](http://upload-images.jianshu.io/upload_images/944365-887b81d9bca4924a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
关于Zip()
结合RxJava
与Rxtrofit
的实例讲解将在第4节中详细讲解
combineLatest()
Observable.combineLatest(
Observable.just(1L, 2L, 3L),
Observable.intervalRange(0, 3, 1, 1, TimeUnit.SECONDS),
new BiFunction<Long, Long, Long>() {
@Override
public Long apply(Long o1, Long o2) throws Exception {
Log.e(TAG, "合并的数据是: "+ o1 + " "+ o2);
return o1 + o2;
}
}).subscribe(new Consumer<Long>() {
@Override
public void accept(Long s) throws Exception {
Log.e(TAG, "合并的结果是: "+s);
}
});
![示意图](http://upload-images.jianshu.io/upload_images/944365-0b9b56ed95835438.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
combineLatestDelayError()
作用类似于concatDelayError()
/ mergeDelayError()
,即错误处理,此处不作过多描述
reduce()
Observable.just(1,2,3,4)
.reduce(new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(@NonNull Integer s1, @NonNull Integer s2) throws Exception {
Log.e(TAG, "本次计算的数据是: "+s1 +" 乘 "+ s2);
return s1 * s2;
}
}).subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer s) throws Exception {
Log.e(TAG, "最终计算的结果是: "+s);
}
});
![示意图](http://upload-images.jianshu.io/upload_images/944365-3f63477c864d7aae.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
collect()
Observable.just(1, 2, 3 ,4, 5, 6)
.collect(
new Callable<ArrayList<Integer>>() {
@Override
public ArrayList<Integer> call() throws Exception {
return new ArrayList<>();
}
}, new BiConsumer<ArrayList<Integer>, Integer>() {
@Override
public void accept(ArrayList<Integer> list, Integer integer)
throws Exception {
list.add(integer);
}
}).subscribe(new Consumer<ArrayList<Integer>>() {
@Override
public void accept(@NonNull ArrayList<Integer> s) throws Exception {
Log.e(TAG, "本次发送的数据是: "+s);
}
});
![示意图](http://upload-images.jianshu.io/upload_images/944365-ab51b84d6a373330.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
3.3 发送事件前追加发送事件
startWith() / startWithArray()
<-- 在一个被观察者发送事件前,追加发送一些数据 -->
Observable.just(4, 5, 6)
.startWith(0)
.startWithArray(1, 2, 3)
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.d(TAG, "接收到了事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "对Error事件作出响应");
}
@Override
public void onComplete() {
Log.d(TAG, "对Complete事件作出响应");
}
});
<-- 在一个被观察者发送事件前,追加发送被观察者 & 发送数据 -->
Observable.just(4, 5, 6)
.startWith(Observable.just(1, 2, 3))
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer value) {
Log.d(TAG, "接收到了事件"+ value );
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "对Error事件作出响应");
}
@Override
public void onComplete() {
Log.d(TAG, "对Complete事件作出响应");
}
});
![示意图](http://upload-images.jianshu.io/upload_images/944365-1fabfa60e8535de2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
![示意图](http://upload-images.jianshu.io/upload_images/944365-23567e0cd790417c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
3.4 统计发送事件数量
count()
Observable.just(1, 2, 3, 4)
.count()
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.e(TAG, "发送的事件数量 = "+aLong);
}
});
![示意图](http://upload-images.jianshu.io/upload_images/944365-45d279a5773edfc2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
至此,RxJava 2
中的组合 / 合并操作符讲解完毕。
4. 实际开发需求案例
下面,我将讲解组合 / 合并操作符的常见实际需求:
1. 从缓存(磁盘、内存)中获取缓存数据
2. 合并数据源
3. 联合判断
- 下面,我将对每个应用场景进行实例Demo演示讲解。
4.1 获取缓存数据
4.2 合并数据源 & 同时展示
4.3 联合判断
5. Demo地址
上述所有的Demo源代码都存放在:Carson_Ho的Github地址:RxJava2_组合 / 合并操作符
6. 总结
- 下面,我将用一张图总结
RxJava2
中常用的组合 / 合并操作符
![示意图](http://upload-images.jianshu.io/upload_images/944365-214478680237ffb8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
- 接下来的时间,我将持续推出
Android
中 Rxjava 2.0
的一系列文章,包括原理、操作符、应用场景、背压等等 ,有兴趣可以继续关注Carson_Ho的安卓开发笔记!!
![示意图](http://upload-images.jianshu.io/upload_images/944365-4c1c1eb44ffe01e5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)