1.前言
在前一篇文章中向大家介绍了过滤操作符,如果对过滤操作符不是很清楚的建议可以去看一下RxJava—过滤操作符。那么在这一章中我们就来介绍RxJava中的组合操作符,这类operators可以同时处理多个Observable来创建我们所需要的Observable。组合操作符主要包括: Merge()、StartWith()、Concat()、Zip()、CombineLatest()、SwitchOnNext()、Join()等等。
2.组合操作符的使用
(1)Merge
merge(Observable, Observable)将两个Observable发射的事件序列组合并成一个事件序列,就像是一个Observable发射的一样。你可以简单的将它理解为两个Observable合并成了一个Observable,合并后的数据是无序的。
根据官方给出的原理图:
我们看下面的例子,一共有两个Observable:一个用来发送字母,另一个用来发送数字;现在我们需要两连个Observable发射的数据合并。
final String[] upperCase = new String[]{"A", "B", "C", "D", "E", "F"};
Observable<String> observableA = Observable.interval(300, TimeUnit.MILLISECONDS)
.map(new Func1<Long, String>()
{
public String call(Long aLong)
{
return upperCase[aLong.intValue()];
}
})
.take(upperCase.length);
Observable<Long> observableB = Observable.interval(500, TimeUnit.MILLISECONDS)
.take(6);
Observable.merge(observableA, observableB)
.subscribe(new Action1<Serializable>()
{
public void call(Serializable serializable)
{
Log.d("merge", serializable.toString());
}
});
所以此时控制台将会打印出:A0BC1D2EF345
merge(Observable[])将多个Observable发射的事件序列组合并成一个事件序列,就像是一个Observable发射的一样。
根据官方给出的原理图:
根据官方给出的原理图:
这里我们将前面Merge操作符的例子拿过来稍做修改,并将操作符换成startWith。
Observable<String> observableA = Observable.just("A", "B", "C", "D", "E", "F");
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
list.add("f");
observableA.startWith(list)
.subscribe(new Action1<String>()
{
public void call(String s)
{
Log.d("startWith", s);
}
});
所以此时控制台将会打印出:abcdefABCDEF
根据官方给出的原理图:
这里我们将前面Merge操作符的例子拿过来稍做修改,并将操作符换成startWith。
Observable<String> observableA = Observable.just("A", "B", "C", "D", "E", "F");
Observable<String> observableB = Observable.just("a", "b", "c", "d", "e", "f");
observableA.startWith(observableB)
.subscribe(new Action1<String>()
{
public void call(String s)
{
Log.d("startWith", s);
}
});
所以此时控制台将会打印出:abcdefABCDEF
(3)Concat
concat(Observable<? extends T>, Observable<? extends T>)和concat(Observable<? extends Observable<T>>)用于将多个Observable发射的的数据进行合并发射,concat严格按照顺序发射数据,前一个Observable没发射玩是不会发射后一个Observable的数据的。它和merge、startWitch和相似,不同之处在于
merge合并后发射的数据是无序的,startWitch只能在源Observable发射的数据前插入数据,而concat是在另一个Observable上进行合并并且合并的发射数据是有序的。
根据官方给出的原理图:
final String[] upperCase = new String[]{"A", "B", "C", "D", "E", "F"};
Observable<String> observableA = Observable.interval(300, TimeUnit.MILLISECONDS)
.map(new Func1<Long, String>()
{
public String call(Long aLong)
{
return upperCase[aLong.intValue()];
}
})
.take(upperCase.length);
Observable<Long> observableB = Observable.interval(500, TimeUnit.MILLISECONDS)
.take(6);
Observable.concat(observableA, observableB)
.subscribe(new Action1<Serializable>()
{
public void call(Serializable serializable)
{
Log.d("concat", serializable.toString());
}
});
根据官方给出的原理图:
Observable<String> observableA = Observable.just("A", "B", "C", "D", "E", "F");
Observable<String> observableB = Observable.just("a", "b", "c", "d", "e", "f");
Observable.zip(observableA, observableB, new Func2<String, String, String>()
{
public String call(String s, String s2)
{
return s + "+" + s2;
}
})
.subscribe(new Action1<String>()
{
public void call(String s)
{
Log.d("zip", s);
}
});
根据官方给出的原理图:
final String[] upperCase = new String[]{"A", "B", "C", "D", "E", "F"};
Observable<String> observableA = Observable.interval(300, TimeUnit.MILLISECONDS)
.map(new Func1<Long, String>()
{
public String call(Long aLong)
{
return upperCase[aLong.intValue()];
}
})
.take(upperCase.length);
Observable<Long> observableB = Observable.interval(500, TimeUnit.MILLISECONDS)
.take(6);
Observable.combineLatest(observableA, observableB, new Func2<String, Long, String>()
{
public String call(String s, Long aLong)
{
return s + "+" + aLong;
}
})
.subscribe(new Action1<String>()
{
public void call(String s)
{
Log.d("combineLatest", s);
}
});
根据官方给出的原理图:
在官方给出的原理图中可以看出黄色的圆形丢失了,这就是因为在黄色的圆形发射时,另一个Observable的黄色的三角形也在发射,这时switchOnNext就会将黄色的圆形抛弃直接发射黄色的三角形。
- Observable:源Observable需要组合的Observable,这里我们姑且称之为目标Observable
- Func1:接收从源Observable发射来的数据,并返回一个Observable,这个Observable的声明周期决定了源Observable发射出来的数据的有效期
- Func1:接收目标Observable发射来的数据,并返回一个Observable,这个Observable的声明周期决定了目标Observable发射出来的数据的有效期
- Func2:接收从源Observable和目标Observable发射出来的数据,并将这两个数据组合后返回
根据官方给出的原理图:
Observable<String> observableA = Observable.just("A", "B", "C", "D", "E", "F");
Observable<String> observableB = Observable.just("1", "2", "3");
observableA.join(observableB,
new Func1<String, Observable<String>>()
{
public Observable<String> call(String s)
{
Log.d("Func1.1", s);
return Observable.just(s).delay(800, TimeUnit.MILLISECONDS);
}
},
new Func1<String, Observable<String>>()
{
public Observable<String> call(String s)
{
Log.d("Func1.2", s);
return Observable.just(s).delay(200, TimeUnit.MILLISECONDS);
}
},
new Func2<String, String, String>()
{
public String call(String s, String s2)
{
return s+s2;
}
})
.subscribe(new Action1<String>()
{
public void call(String s)
{
Log.d("join", s);
}
});
通过控制台打印出的结果可以看出,第一个Func1接收从源Observable发射来的数据并且数据全部发送完毕以后,才到第二个Func1,在第二个Func1中接收目标Observable发射来的数据,并且目标Observable每发射一个数据就根据Func2中的组合规则进行组合并且发射。