一.buffer操作符
buffer操作符周期性地收集源Observable產生的結果到列表中,并把這個列表提交給訂閱者,訂閱者處理后,清空buffer列表,同時接收下一次收集的結果并提交給訂閱者,周而復始。需要注意的是,一旦源Observable在產生結果的過程中出現異常,即使buffer已經存在收集到的結果,訂閱者也會馬上收到這個異常,并結束整個過程。
//定義郵件內容
final String[] mails = new String[]{"Here is an email!", "Another email!", "Yet another email!"};
//每隔1秒就隨機發布一封郵件
Observable<String> endlessMail = Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
try {
if (subscriber.isUnsubscribed()) return;
Random random = new Random();
while (true) {
String mail = mails[random.nextInt(mails.length)];
subscriber.onNext(mail);
Thread.sleep(1000); }
} catch (Exception ex) {
subscriber.onError(ex);
}
}
}).subscribeOn(Schedulers.io());
//把上面產生的郵件內容緩存到列表中,并每隔3秒通知訂閱者
endlessMail.buffer(3, TimeUnit.SECONDS).subscribe(new Action1<List<String>>() {
@Override
public void call(List<String> list) {
System.out.println(String.format("You've got %d new messages! Here they are!", list.size()));
for (int i = 0; i < list.size(); i++)
System.out.println(list.get(i).toString());
}
});
打印出的結果:
You’ve got 3 new messages! Here they are!(after 3s)
Here is an email!
Another email!
Another email!
You’ve got 3 new messages! Here they are!(after 6s)
Here is an email!
Another email!
Here is an email!
……
二.flatMap操作符
flatMap操作符是把Observable產生的結果轉換成多個Observable,然后把這多個Observable“扁平化”成一個Observable,并依次提交產生的結果給訂閱者。flatMap操作符通過傳入一個函數作為參數轉換源Observable,在這個函數中,你可以自定義轉換規則,最后在這個函數中返回一個新的Observable,然后flatMap操作符通過合并這些Observable結果成一個Observable,并依次提交結果給訂閱者。
private Observable<File> listFiles(File f){
if(f.isDirectory()){
return Observable.from(f.listFiles())
.flatMap(new Func1<File, Observable<File>>() {
@Override
public Observable<File> call(File file) {
return listFiles(f);
}
});
} else {
return Observable.just(f);
}
}
@Override
public void onClick(View v) {
Observable.just(getApplicationContext().getExternalCacheDir())
.flatMap(new Func1<File, Observable<File>>() {
@Override
public Observable<File> call(File file) {
//參數file是just操作符產生的結果,這里判斷file是不是目錄文件,如果是目錄文件,則遞歸查找其子文件flatMap操作符神奇的地方在于,
//返回的結果還是一個Observable,而這個Observable其實是包含多個文件的Observable的,輸出應該是ExternalCacheDir下的所有文件
return listFiles(file); }
}) .subscribe(new Action1<File>() {
@Override
public void call(File file) {
System.out.println(file.getAbsolutePath());
}
});
}
三.concatMap操作符
cancatMap操作符與flatMap操作符類似,都是把Observable產生的結果轉換成多個Observable,然后把這多個Observable“扁平化”成一個Observable,并依次提交產生的結果給訂閱者。與flatMap操作符不同的是,concatMap操作符在處理產生的Observable時,采用的是“連接(concat)”的方式,而不是“合并(merge)”的方式,這就能保證產生結果的順序性,也就是說提交給訂閱者的結果是按照順序提交的,不會存在交叉的情況。
四.switchMap操作符
switchMap操作符與flatMap操作符類似,都是把Observable產生的結果轉換成多個Observable,然后把這多個Observable“扁平化”成一個Observable,并依次提交產生的結果給訂閱者。與flatMap操作符不同的是,switchMap操作符會保存最新的Observable產生的結果而舍棄舊的結果,舉個例子來說,比如源Observable產生A、B、C三個結果,通過switchMap的自定義映射規則,映射后應該會產生A1、A2、B1、B2、C1、C2,但是在產生B2的同時,C1已經產生了,這樣最后的結果就變成A1、A2、B1、C1、C2,B2被舍棄掉了!
//flatMap操作符的運行結果
Observable.just(10, 20, 30)
.flatMap(new Func1<Integer, Observable<Integer>>() {
@Override
public Observable<Integer> call(Integer integer) {
//10的延遲執行時間為200毫秒、20和30的延遲執行時間為180毫秒
int delay = 200;
if (integer > 10) delay = 180;
return Observable.from(new Integer[]{integer, integer / 2})
.delay(delay, TimeUnit.MILLISECONDS);
} })
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println("flatMap Next:" + integer);
} });
//concatMap操作符的運行結果
Observable.just(10, 20, 30)
.concatMap(new Func1<Integer, Observable<Integer>>() {
@Override
public Observable<Integer> call(Integer integer) {
//10的延遲執行時間為200毫秒、20和30的延遲執行時間為180毫秒
int delay = 200;
if (integer > 10) delay = 180;
return Observable.from(new Integer[]{integer, integer / 2})
.delay(delay, TimeUnit.MILLISECONDS); } })
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println("concatMap Next:" + integer);
} });
//switchMap操作符的運行結果
Observable.just(10, 20, 30)
.switchMap(new Func1<Integer, Observable<Integer>>() {
@Override
public Observable<Integer> call(Integer integer) {
//10的延遲執行時間為200毫秒、20和30的延遲執行時間為180毫秒
int delay = 200;
if (integer > 10) delay = 180;
return Observable.from(new Integer[]{integer, integer / 2})
.delay(delay, TimeUnit.MILLISECONDS);
} })
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
System.out.println("switchMap Next:" + integer); } });
運行結果如下:
flatMap Next:20
flatMap Next:10
flatMap Next:30
flatMap Next:15
flatMap Next:10
flatMap Next:5
switchMap Next:30
switchMap Next:15
concatMap Next:10
concatMap Next:5
concatMap Next:20
concatMap Next:10
concatMap Next:30
concatMap Next:15
五.groupBy操作符
groupBy操作符是對源Observable產生的結果進行分組,形成一個類型為GroupedObservable的結果集,GroupedObservable中存在一個方法為getKey(),可以通過該方法獲取結果集的Key值(類似于HashMap的key)。值得注意的是,由于結果集中的GroupedObservable是把分組結果緩存起來,如果對每一個GroupedObservable不進行處理(既不訂閱執行也不對其進行別的操作符運算),就有可能出現內存泄露。因此,如果你對某個GroupedObservable不進行處理,最好是對其使用操作符take(0)處理。