上一篇中講了Rxjava的基本使用,這篇來講一下Rxjava的一些高級操作
一.Rxjava中的變換
RxJava 提供了對事件序列進(jìn)行變換的支持,這是它的核心功能之一,也是大多數(shù)人說 “RxJava 真是太好用了” 的最大原因。所謂變換,就是將事件序列中的對象或整個(gè)序列進(jìn)行加工處理,轉(zhuǎn)換成不同的事件或事件序列。
首先看一個(gè) map() 的例子:
Observable.just("images/logo.png") // 輸入類型 String
.map(new Func1<String, Bitmap>() {
@Override
public Bitmap call(String filePath) { // 參數(shù)類型 String
return getBitmapFromPath(filePath); // 返回類型 Bitmap
}
})
.subscribe(new Action1<Bitmap>() {
@Override
public void call(Bitmap bitmap) { // 參數(shù)類型 Bitmap
showBitmap(bitmap);
}
});
可以看到,map() 方法將參數(shù)中的 String 對象轉(zhuǎn)換成一個(gè) Bitmap 對象后返回,而在經(jīng)過 map() 方法后,事件的參數(shù)類型也由 String 轉(zhuǎn)為了 Bitmap。這種直接變換對象并返回的,是最常見的也最容易理解的變換。不過 RxJava 的變換遠(yuǎn)不止這樣,它不僅可以針對事件對象,還可以針對整個(gè)事件隊(duì)列,這使得 RxJava 變得非常靈活。
再看一個(gè) flatMap() 的例子:
String[] filePaths = ...;
Subscriber<Bitmap> subscriber = new Subscriber<Bitmap>() {
@Override
public void onNext(Bitmap bitmap) {
...
}
...
};
Observable.from(filePaths)
.flatMap(new Func1<String, Observable<Bitmap>>() {
@Override
public Observable<Bitmap> call(String filePath) {
return Observable.from(getAllPhoto(filePath));
}
})
.subscribe(subscriber);
從上面的代碼可以看出, flatMap() 和 map() 有一個(gè)相同點(diǎn):它也是把傳入的參數(shù)轉(zhuǎn)化之后返回另一個(gè)對象。但需要注意,和 map() 不同的是, flatMap() 中返回的是個(gè) Observable 對象,并且這個(gè) Observable 對象并不是被直接發(fā)送到了 Subscriber 的回調(diào)方法中。
flatMap() 的原理是這樣的:1. 使用傳入的事件對象創(chuàng)建一個(gè) Observable 對象;2. 并不發(fā)送這個(gè) Observable, 而是將它激活,于是它開始發(fā)送事件;3. 每一個(gè)創(chuàng)建出來的 Observable 發(fā)送的事件,都被匯入同一個(gè) Observable ,而這個(gè) Observable 負(fù)責(zé)將這些事件統(tǒng)一交給 Subscriber 的回調(diào)方法。這三個(gè)步驟,把事件拆成了兩級,通過一組新創(chuàng)建的 Observable 將初始的對象『鋪平』之后通過統(tǒng)一路徑分發(fā)了下去。而這個(gè)『鋪平』就是 flatMap() 所謂的 flat
二.Rxjava中的Subject
關(guān)于Subject,官方文檔的解釋是這樣的:Subject可以看成是一個(gè)橋梁或者代理,在某些ReactiveX實(shí)現(xiàn)中(如RxJava),它同時(shí)充當(dāng)了Observer和Observable的角色。因?yàn)樗且粋€(gè)Observer,它可以訂閱一個(gè)或多個(gè)Observable;又因?yàn)樗且粋€(gè)Observable,它可以轉(zhuǎn)發(fā)它收到(Observe)的數(shù)據(jù),也可以發(fā)射新的數(shù)據(jù)。從官方解釋中,我提取出三個(gè)要點(diǎn):
它可以充當(dāng)Observable;
它可以充當(dāng)Observer;
它是Observable和Observer之間的橋梁;
Subject的分類解析
** AsyncSubject**
Observer會(huì)接收AsyncSubject的onComplete()
之前的最后一個(gè)數(shù)據(jù),如果因異常而終止,AsyncSubject將不會(huì)釋放任何數(shù)據(jù),但是會(huì)向Observer傳遞一個(gè)異常通知。** BehaviorSubject**
Observer會(huì)接收到BehaviorSubject被訂閱之前的最后一個(gè)數(shù)據(jù),再接收其他發(fā)射過來的數(shù)據(jù),如果BehaviorSubject被訂閱之前沒有發(fā)送任何數(shù)據(jù),則會(huì)發(fā)送一個(gè)默認(rèn)數(shù)據(jù)。** PublishSubject**
PublishSubject比較容易理解,相對比其他Subject常用,它的Observer只會(huì)接收到PublishSubject被訂閱之后發(fā)送的數(shù)據(jù)。** ReplaySubject**
ReplaySubject會(huì)發(fā)射所有數(shù)據(jù)給觀察者,無論它們是何時(shí)訂閱的。也有其它版本的ReplaySubject,在重放緩存增長到一定大小的時(shí)候或過了一段時(shí)間后會(huì)丟棄舊的數(shù)據(jù)。
接下來用代碼說明它如何充當(dāng)Observable,Observer以及Observable和Observer之間的橋梁:
創(chuàng)建Observable并發(fā)射數(shù)據(jù):
PublishSubject<String> publishSubject = PublishSubject.create();
publishSubject.onNext("as Observable");
publishSubject.onCompleted();```
創(chuàng)建Observer訂閱Observable并接收數(shù)據(jù):
publishSubject.subscribe(new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
}
});```
借用Subject來連接Observable和Observer:
PublishSubject<String> publishSubject = PublishSubject.create();
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("as Bridge");
subscriber.onCompleted();
}
}).subscribe(publishSubject);
publishSubject.subscribe(new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
...
}
});```