注:本文摘自《RxJava Essentials》翻譯中文版電子書
過濾序列
使用filter()方法來過濾我們觀測序列中不想要的值。只要條件符合filter()函數(shù)就會返回true饥侵。例如:
//過濾,只要C開頭的
.filter(new Func1<AppInfo,Boolean>(){
@Override
public Boolean call(AppInfo appInfo){
return appInfo.getName().startsWith("C");
}
})
//過濾null的對象
.filter(new Func1<AppInfo,Boolean>(){
@Override
public Boolean call(AppInfo appInfo){
return appInfo != null;
}
})
獲取我們需要的數(shù)據(jù)
如果只想取開頭或結尾的幾個元素,我們可以用take()或takeLast():
//獲取一個可觀測序列中的前三個元素
private void loadList(List<AppInfo> apps) {
Observable.from(apps)
.take(3)
.subscribe(/**代碼省略**/);
}
//獲取最后N個元素
Observable.from(apps)
.takeLast(3)
.subscribe(...);
有且僅有一次
Distinct
如果我們想對一個指定的值僅處理一次該怎么辦丹皱?我們可以對我們的序列使用distinct()
函數(shù)去掉重復的。就像takeLast()一樣宋税,distinct()作用于一個完整的序列摊崭,然后得到重復的過濾項,它需要記錄每一個發(fā)射的值杰赛。如果你在處理一大堆序列或者大的數(shù)據(jù)記得關注內存使用情況呢簸。
例子:
Observable<AppInfo> fullOfDuplicates = Observable.from(apps) .take(3) .repeat(3);
- take():它有一小組的可識別的數(shù)據(jù)項。
- repeat():創(chuàng)建一個有重復的大的序列乏屯。
fullOfDuplicates 變量里把我們已安裝應用的前三個重復了3次:有9個并且許多重復的根时。然后,我們使用distinct()函數(shù)來去除重復:
fullOfDuplicates.distinct().subscribe(...);
DistinctUntilsChanged
引出問題:
如果在一個可觀測序列發(fā)射一個不同于之前的一個新值時讓我們得到通知這時候該怎么做辰晕?我們猜想一下我們觀測的溫度傳感器蛤迎,每秒發(fā)射的室內溫度:
21°...21°...21°...21°...22°...
每次我們獲得一個新值,我們都會更新當前正在顯示的溫度含友。我們出于系統(tǒng)資源保護并不想在每次值一樣時更新數(shù)據(jù)替裆。我們想忽略掉重復的值并且在溫度確實改變時才想得到通知。
ditinctUntilChanged()過濾函數(shù)能做到這一點窘问。它能輕易的忽略掉所有的重復并且只發(fā)射出新的值辆童。
First and last
從一個從可觀測源序列中創(chuàng)建只發(fā)射第一個元素的序列。
first()方法和last()方法很容易弄明白惠赫。它們從Observable中只發(fā)射第一個元素或者最后一個元素胸遇。
與first()和last()相似的變量有:firstOrDefault()和lastOrDefault()。這兩個函數(shù)當可觀測序列完成時不再發(fā)射任何值時用得上汉形。在這種場景下,如果Observable不再發(fā)射任何值時我們可以指定發(fā)射一個默認的值倍阐。
Skip and SkipLast
創(chuàng)建一個不發(fā)射前N個元素而是發(fā)射它后面的那些數(shù)據(jù)的序列或者跳過后面N個元素從源序列中發(fā)射剩下的其他元素概疆。
skip()和skipLast()函數(shù)與take()和takeLast()相對應。它們用整數(shù)N作參數(shù)峰搪,從本質上來說岔冀,它們不讓Observable發(fā)射前N個或者后N個值。如果我們知道一個序列以沒有太多用的“可控”元素開頭或結尾時我們可以使用它概耻。
ElementAt
如果我們只想要可觀測序列發(fā)射的第五個元素該怎么辦使套?elementAt()函數(shù)僅從一個序列中發(fā)射第n個元素然后就完成了罐呼。
如果我們想查找第五個元素但是可觀測序列只有三個元素可供發(fā)射時該怎么辦?我們可以使用elementAtOrDefault()侦高。
Sampling
回到那個溫度傳感器問題嫉柴,每秒都會發(fā)射當前室內的溫度。說實話奉呛,我們并不認為溫度會變化這么快计螺,我們可以使用一個小的發(fā)射間隔。在Observable后面加一個sample()瞧壮,我們將創(chuàng)建一個新的可觀測序列登馒,它將在一個指定的時間間隔里由Observable發(fā)射最近一次的數(shù)值:
Observable<Integer> sensor = [...]
sensor.sample(30,TimeUnit.SECONDS)
.subscribe(...);
上面例子Observable將會觀測溫度Observable然后每隔30秒就會發(fā)射最后一個溫度值。sample()支持全部的時間單位:秒咆槽,毫秒陈轿,天,分等等秦忿。
下圖中展示了一個間隔發(fā)射字母的Observable如何采樣一個發(fā)射數(shù)字的Observable麦射。Observable的結果將會發(fā)射每個已發(fā)射字母的最后一組數(shù)據(jù):1,4小渊,5.
如果我們想讓它定時發(fā)射第一個元素而不是最近的一個元素法褥,我們可以使用throttleFirst()
Timeout
假設我們工作的是一個時效性的環(huán)境,我們溫度傳感器每秒都在發(fā)射一個溫度值酬屉。我們想讓它每隔兩秒至少發(fā)射一個半等,我們可以使用timeout()函數(shù)來監(jiān)聽源可觀測序列,就是在我們設定的時間間隔內如果沒有得到一個值則發(fā)射一個錯誤。我們可以認為timeout()為一個Observable的限時的副本呐萨。如果在指定的時間間隔內Observable不發(fā)射值的話杀饵,它監(jiān)聽的原始的Observable時就會觸發(fā)onError()函數(shù)。
Subscription subscription = getCurrentTemperature()
.timeout(2,TimeUnit.SECONDS)
.subscribe(...);
Debounce
debounce()函數(shù)過濾掉由Observable發(fā)射的速率過快的數(shù)據(jù)谬擦;如果在一個指定的時間間隔過去了仍舊沒有發(fā)射一個切距,那么它將發(fā)射最后的那個。
就像sample()和timeout()函數(shù)一樣惨远,debounce()使用TimeUnit對象指定時間間隔谜悟。