一個可觀測序列會在出錯時重復(fù)發(fā)射或者被設(shè)計成重復(fù)發(fā)射。distinct()
和distinctUntilChanged()
函數(shù)可以方便的讓我們處理這種重復(fù)問題。
如果我們想對一個指定的值僅處理一次該怎么辦?我們可以對我們的序列使用distinct()
函數(shù)去掉重復(fù)的。就像takeLast()
一樣,distinct()
作用于一個完整的序列,然后得到重復(fù)的過濾項,它需要記錄每一個發(fā)射的值。如果你在處理一大堆序列或者大的數(shù)據(jù)記得關(guān)注內(nèi)存使用情況。
下圖展示了如何在一個發(fā)射1和2兩次的可觀測源上創(chuàng)建一個無重的序列: http://wiki.jikexueyuan.com/project/rxjava/images/chapter4_5.png" alt="" />
為了創(chuàng)建我們例子中序列,我們將使用我們至今已經(jīng)學(xué)到的幾個方法:
take()
:它有一小組的可識別的數(shù)據(jù)項。repeat()
:創(chuàng)建一個有重復(fù)的大的序列。然后,我們將應(yīng)用distinct()
函數(shù)來去除重復(fù)。
我們用程序?qū)崿F(xiàn)一個重復(fù)的序列,然后過濾出它們。這聽起來時不可思議的,但是為了實現(xiàn)這個例子來使用我們至今為止已學(xué)習(xí)到的東西則是個不錯的練習(xí)。
Observable<AppInfo> fullOfDuplicates = Observable.from(apps)
.take(3)
.repeat(3);
fullOfDuplicates
變量里把我們已安裝應(yīng)用的前三個重復(fù)了3次:有9個并且許多重復(fù)的。然后,我們使用distinct()
:
fullOfDuplicates.distinct()
.subscribe(new Observer<AppInfo>() {
@Override
public void onCompleted() {
mSwipeRefreshLayout.setRefreshing(false);
}
@Override
public void onError(Throwable e) {
Toast.makeText(getActivity(), "Something went wrong!", Toast.LENGTH_SHORT).show();
mSwipeRefreshLayout.setRefreshing(false);
}
@Override
public void onNext(AppInfo appInfo) {
mAddedApps.add(appInfo);
mAdapter.addApplication(mAddedApps.size() - 1,appInfo);
}
});
}
結(jié)果,很明顯,我們得到:
http://wiki.jikexueyuan.com/project/rxjava/images/chapter4_6.png" alt="" />
如果在一個可觀測序列發(fā)射一個不同于之前的一個新值時讓我們得到通知這時候該怎么做?我們猜想一下我們觀測的溫度傳感器,每秒發(fā)射的室內(nèi)溫度:
21°...21°...21°...21°...22°...
每次我們獲得一個新值,我們都會更新當(dāng)前正在顯示的溫度。我們出于系統(tǒng)資源保護(hù)并不想在每次值一樣時更新數(shù)據(jù)。我們想忽略掉重復(fù)的值并且在溫度確實改變時才想得到通知。ditinctUntilChanged()
過濾函數(shù)能做到這一點。它能輕易的忽略掉所有的重復(fù)并且只發(fā)射出新的值。
下圖用圖形化的方式展示了我們?nèi)绾螌?code>distinctUntilChanged()函數(shù)應(yīng)用在一個存在的序列上來創(chuàng)建一個新的不重復(fù)發(fā)射元素的序列。
http://wiki.jikexueyuan.com/project/rxjava/images/chapter4_7.png" alt="" />