1、组合操作符
(1)、组合多个观察者:concat() / concatArray()
作用:组合多个 被观测者 一起发送数据,合并后 按发送顺序串行执行
两者的区别:组合被观察者的数量,concat()组合被观察者 <=4,而 concatArray()则可以>=5
具体使用:
Observable
//创建组合操作符(concat必须,<=4个)
.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 integer) {
System.out.println("接收到的数据"+integer);
}
@Override
public void onError(Throwable e) {
System.out.println("对Error事件作出响应");
}
@Override
public void onComplete() {
System.out.println("对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),
Observable.just(16,17,18)
)
//订阅
.subscribe(
new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer i) {
System.out.println("接收到的事件"+i);
}
@Override
public void onError(Throwable e) {
System.out.println("对Error事件作出响应");
}
@Override
public void onComplete() {
System.out.println("对Complete事件作出响应");
}
}
);
运行的结果:
(2)、merge() / mergeArray()
作用:组合多个被观察者一起发送数据, 合并后 按时间线并执行
两者的区别:merge<=4,mergeArray>4个。
具体使用:
Observable
.merge(
//从事件0开始接收,事件数量为3,延迟1秒执行,间隔为3秒
Observable.intervalRange(0,3,1,1,TimeUnit.SECONDS),
//从事件10开始接收,事件数量为3,延迟1秒执行,间隔为3秒
Observable.intervalRange(10,3,1,1,TimeUnit.SECONDS)
)
.subscribe(
new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Long aLong) {
System.out.println("接收事件:"+aLong);
}
@Override
public void onError(Throwable e) {
System.out.println("对Error作出响应");
}
@Override
public void onComplete() {
System.out.println("对Complete作出响应");
}
}
);
(3)、concatDelayError() / mergeDelayError()
作用:
举例,如果不使用concatDelayError()的情况
Observable.concat(
//创建被观察者1
Observable.create(
new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
e.onNext(1);
e.onNext(2);
e.onNext(3);
e.onNext(4);
e.onError(new NullPointerException());
e.onComplete();
}
}
),
//创建被观察者2
Observable.just(5,6,7))
.subscribe(
new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
System.out.println("接收到的事件:"+integer);
}
@Override
public void onError(Throwable e) {
System.out.println("对Error事件作出响应"+e);
}
@Override
public void onComplete() {
System.out.println("对Complete作出响应");
}
}
);
运行结果:
第1个被观察者发送Error事件以后,第2个观察者则不会继续发送事件。
对 concatArrayDelayError:
Observable.concatArrayDelayError(
//创建观察者1
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
e.onNext(1);
e.onNext(2);
e.onNext(3);
e.onNext(4);
e.onError(new NullPointerException());
}
}),
//创建观察者2
Observable.just(5,6,7)
)
//订阅
.subscribe(
new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer integer) {
System.out.println("接收到的事件"+integer);
}
@Override
public void onError(Throwable e) {
System.out.println("对Error事件作出响应"+e);
}
@Override
public void onComplete() {
System.out.println("对Complete事件作出响应");
}
}
);
运行结果:
2、合并操作符:主要是对多个被观察者中的事件进行合并处理
(1) Zip()
作用:合并 多个被观察者发送的事件,生成一个新的事件序列,并发送
原理:
注意:
1)、事件组合方式=严格按照原先事件序列 进行对位合并
2)、最终合并的事件数量 = 多个被观察者中数量最少的
具体的使用:
//创建被观察者1
Observable<Integer> observable1=Observable.create(
new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> e) throws Exception {
System.out.println("被观察者1发送的事件1");
e.onNext(1);
System.out.println("被观察者1发送的事件2");
e.onNext(2);
System.out.println("被观察者1发送的事件3");
e.onNext(3);
}
}
)
//在子线程中
.subscribeOn(Schedulers.io());
//创建被观测者2
Observable<String> observable2=Observable.create(
new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> e) throws Exception {
System.out.println("被观察者2发送的事件A");
e.onNext("A");
System.out.println("被观察者2发送的事件B");
e.onNext("B");
System.out.println("被观察者2发送的事件C");
e.onNext("D");
System.out.println("被观察者2发送的事件D");
e.onNext("D");
System.out.println("被观察者2发送的事件E");
e.onNext("E");
}
}
)
//假设被观察者1和被观察者2不做线程控制的话,两个会在同一个线程中执行,则发送事件会有先后的顺序,而不同的线程就是并发执行
.subscribeOn(Schedulers.newThread());
Observable
//合并
.zip(
//第3个参数:合并后的数据类型
observable1,observable2, new BiFunction<Integer, String, String>() {
@Override
public String apply(@NonNull Integer integer, @NonNull String s) throws Exception {
return integer+s;//返回合并的结果
}
})
//订阅
.subscribe(
//创建观察者
new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
System.out.println("最终接收到的事件:"+s);
}
@Override
public void onError(Throwable e) {
System.out.println("对事件Error作出响应"+e);
}
@Override
public void onComplete() {
System.out.println("对事件Complete作出响应");
}
}
);
注意:有上面的运行结果可以看出,尽管被观察者2的事件 D E 没有事件与其合并,当时还会被继续的发送
但是若是,被观察者1与被观察者2的事件序列最后都发送onComplete()事件,则被观察者2的 D E 事件是不会被发送的。
总结:Zip操作符比较难理解,这也是非常的重要.
应用场景:(1)、例一:但需要展示的信息从多个地方获取的(最终的结果 = 实体1 + 实体2)并且 统一的展示
(2)、例二:合并网络请求的发送并且统一显示结果
3)、Zip项目中的实际应用:
不多说,直接上我项目中的实际应用。如图:下面两个框访问的是两个接口。我要实现的效果是:通过zip实现两个接口返回的实体数据 合并到 一个实体当中.
直接上代码:
①封装一下Retrofit:
②、接口
③、两个接口返回的数据实体(这个我就不和大家列出来了,反正不影响理解接下来的代码,想体验随便找连个接口访问就行)
④、合并后的实体
⑤、接口访问,zip合并:
Observable<PlayerCountAndPriceEntity> observable1 = RetrofitFactory.getRetrofit().create(NetApi.class).requestTheme();
Observable<ThemeEntity> observable2 = RetrofitFactory.getRetrofit().create(NetApi.class).requestThemeSort();
observable1.subscribeOn(Schedulers.io())
.subscribe(
new Consumer<PlayerCountAndPriceEntity>() {
@Override
public void accept(@NonNull PlayerCountAndPriceEntity countAndPriceEntity) throws Exception {
System.out.println("获取到人数和价格筛选实体:" + countAndPriceEntity);
}
}
);
observable2.subscribeOn(Schedulers.io())
.subscribe(
new Consumer<ThemeEntity>() {
@Override
public void accept(@NonNull ThemeEntity themeNameEntity) throws Exception {
System.out.println("获取到主题实体:" + themeNameEntity);
}
}
);
Observable.zip(observable1, observable2, new BiFunction<PlayerCountAndPriceEntity, ThemeEntity, UltimatelyEntity>() {
@Override
public UltimatelyEntity apply(@NonNull PlayerCountAndPriceEntity themeSearchEntity, @NonNull ThemeEntity themeNameEntity) throws Exception {
UltimatelyEntity entity = new UltimatelyEntity();
entity.setSearchData(themeSearchEntity.getData());
entity.setNameEntity(themeNameEntity);
return entity;
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
new Observer<UltimatelyEntity>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(UltimatelyEntity totalEntity) {
//根据合并后的实体更新UI数据,效果就是我开始给的那张效果图了,我这里就不写了
System.out.println("zip操作符合并后的实体:" + totalEntity);
}
@Override
public void onError(Throwable e) {
System.out.println("数据异常" + e);
}
@Override
public void onComplete() {
}
}
);
}
这样就搞定了zip()了,是不是很简单。不知道大家理解到zip的实际开发中的场景没有。不懂没关系我再给大家举个开发中很常见的例子:
例如将第三方的广告夹杂进自家的平台返回的数据当中。这种并行的异步比较麻烦,不过通过zip()就非常的简单实现了.
(2)combineLatest()
1)作用:两个被观察者中的任何一个发送数据后,将先发送数据的那个被观察者的 最新的(也就是最后发送的那个数据),与另一个观察者发送的 每一个 数据合并。
2)区别:与zip的区别就是,zip按个数合并,是一对一的合并。combineLatest是按照时间点合并 。
Observable.combineLatest(
Observable.just("我是数据1,", "无数数据2,", "我是数据3,"),
Observable.intervalRange(0, 3, 1, 1, TimeUnit.SECONDS),
new BiFunction<String, Long, String>() {
@Override
public String apply(@NonNull String s, @NonNull Long aLong) throws Exception {
return s+aLong;
}
}
).subscribe(
new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(String s) {
System.out.println("接收事件结果:"+s);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
}
);
运行结果:
(3)、combineLatestDelayError()
作用类似于concatDelayError/mergeDelayError.
(4)、reduce()
作用:把被观察者发送的事件进行聚合成一个事件并且发送(聚合的逻辑根据需求来写,但是本质就是:前两个数据聚合以后再与后1个数据继续进行聚合)
Observable.just(1,2,3,4,5)
.reduce(new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(@NonNull Integer integer, @NonNull Integer integer2) throws Exception {
System.out.println("本次计算的结果"+integer+"+"+integer2);
return integer+integer2;
}
})
.subscribe(new Consumer<Integer>() {
@Override
public void accept(@NonNull Integer integer) throws Exception {
//本质就是:1+2+3+4+5
System.out.println("reduce:聚合的最终结果:"+integer);
}
});
运行的结果:
(5)、collect()
作用:将被观察者发送的数据事件收集到一个数据结构里
运行结果:
3、发送事件前追加发送事件
startWith() / startWitchArray()
作用:在一个被观察者发射事件之前,追加一些数据 或者 一个新的被观察者
追加一些数据:
运行结果:
追加被观察者:
运行结果:
4、统计发送的数量
count()
作用:统计被观察者发送的数量.
运行结果: