RxJava2 實戰(zhàn)系列文章
RxJava2 實戰(zhàn)知識梳理(1) - 后臺執(zhí)行耗時操作,實時通知 UI 更新
RxJava2 實戰(zhàn)知識梳理(2) - 計算一段時間內(nèi)數(shù)據(jù)的平均值
RxJava2 實戰(zhàn)知識梳理(3) - 優(yōu)化搜索聯(lián)想功能
RxJava2 實戰(zhàn)知識梳理(4) - 結(jié)合 Retrofit 請求新聞資訊
RxJava2 實戰(zhàn)知識梳理(5) - 簡單及進(jìn)階的輪詢操作
RxJava2 實戰(zhàn)知識梳理(6) - 基于錯誤類型的重試請求
RxJava2 實戰(zhàn)知識梳理(7) - 基于 combineLatest 實現(xiàn)的輸入表單驗證
RxJava2 實戰(zhàn)知識梳理(8) - 使用 publish + merge 優(yōu)化先加載緩存掸茅,再讀取網(wǎng)絡(luò)數(shù)據(jù)的請求過程
RxJava2 實戰(zhàn)知識梳理(9) - 使用 timer/interval/delay 實現(xiàn)任務(wù)調(diào)度
RxJava2 實戰(zhàn)知識梳理(10) - 屏幕旋轉(zhuǎn)導(dǎo)致 Activity 重建時恢復(fù)任務(wù)
RxJava2 實戰(zhàn)知識梳理(11) - 檢測網(wǎng)絡(luò)狀態(tài)并自動重試請求
RxJava2 實戰(zhàn)知識梳理(12) - 實戰(zhàn)講解 publish & replay & share & refCount & autoConnect
RxJava2 實戰(zhàn)知識梳理(13) - 如何使得錯誤發(fā)生時不自動停止訂閱關(guān)系
RxJava2 實戰(zhàn)知識梳理(14) - 在 token 過期時卑笨,刷新過期 token 并重新發(fā)起請求
RxJava2 實戰(zhàn)知識梳理(15) - 實現(xiàn)一個簡單的 MVP + RxJava + Retrofit 應(yīng)用
一、前言
今天夭拌,我們繼續(xù)跟著 RxJava-Android-Samples 的腳步,一起看一下RxJava2
在實戰(zhàn)當(dāng)中的應(yīng)用,在這個項目中,第二個的例子的描述如下:
簡單地翻譯過來:如果在
2s
內(nèi)連續(xù)點擊了一個按鈕五次音羞,那么我們只會收到一個“你點擊了該按鈕五次”的時間,而不是五個"你點擊了該按鈕"的事件仓犬。這個示例的目的是讓我們學(xué)會如何應(yīng)用buffer
操作符嗅绰。
二、示例
2.1 應(yīng)用場景
仔細(xì)思考了一下搀继,在平時的項目中窘面,我們似乎不會遇到需要統(tǒng)計一段時間內(nèi)用戶點擊了多少次按鈕這種需求。
但是叽躯,我們有時候會需要計算一段時間內(nèi)的平均數(shù)據(jù)民镜,例如統(tǒng)計一段時間內(nèi)的平均溫度,或者統(tǒng)計一段時間內(nèi)的平均位置险毁。在接觸RxJava
之前制圈,我們一般會將這段時間內(nèi)統(tǒng)計到的數(shù)據(jù)都暫時存起來们童,等到需要更新的時間點到了之后,再把這些數(shù)據(jù)結(jié)合起來鲸鹦,計算這些數(shù)據(jù)的平均值慧库。
現(xiàn)在,我們就來看一下馋嗜,用RxJava2
如何去實現(xiàn)這個需求齐板。
2.2 示例代碼
這里,我們通過一個Handler
循環(huán)地發(fā)送消息葛菇,實現(xiàn)間隔一定時間進(jìn)行溫度的測量甘磨,但是在測量之后,我們并不實時地更新界面的溫度顯示眯停,而是每隔3s
統(tǒng)計一次過去這段時間內(nèi)的平均溫度济舆。
public class BufferActivity extends AppCompatActivity {
private PublishSubject<Double> mPublishSubject;
private CompositeDisposable mCompositeDisposable;
private TextView mTv;
private SourceHandler mSourceHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_buffer);
mTv = (TextView) findViewById(R.id.tv_buffer);
mPublishSubject = PublishSubject.create();
DisposableObserver<List<Double>> disposableObserver = new DisposableObserver<List<Double>>() {
@Override
public void onNext(List<Double> o) {
double result = 0;
if (o.size() > 0) {
for (Double d : o) {
result += d;
}
result = result / o.size();
}
Log.d("BufferActivity", "更新平均溫度:" + result);
mTv.setText("過去3秒收到了" + o.size() + "個數(shù)據(jù), 平均溫度為:" + result);
}
@Override
public void onError(Throwable throwable) {
}
@Override
public void onComplete() {
}
};
mPublishSubject.buffer(3000, TimeUnit.MILLISECONDS).observeOn(AndroidSchedulers.mainThread()).subscribe(disposableObserver);
mCompositeDisposable = new CompositeDisposable();
mCompositeDisposable.add(disposableObserver);
//開始測量溫度莺债。
mSourceHandler = new SourceHandler();
mSourceHandler.sendEmptyMessage(0);
}
public void updateTemperature(double temperature) {
Log.d("BufferActivity", "溫度測量結(jié)果:" + temperature);
mPublishSubject.onNext(temperature);
}
private class SourceHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
double temperature = Math.random() * 25 + 5;
updateTemperature(temperature);
//循環(huán)地發(fā)送滋觉。
sendEmptyMessageDelayed(0, 250 + (long) (250 * Math.random()));
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mSourceHandler.removeCallbacksAndMessages(null);
mCompositeDisposable.clear();
}
}
實際的運行結(jié)果為:
控制臺輸出的信息為:
三、示例解析
3.1 原理
在上面的例子中齐邦,我們使用了buffer(int time, Unit timeUnit)
椎侠,其原理圖如下所示:
函數(shù)中的兩個形參分別對應(yīng)是時間的值和單位,這樣措拇,當(dāng)我們通過下面這句發(fā)送事件:
mPublishSubject.onNext(temperature);
事件并不會直接傳遞到Observer
的onNext
方法中我纪,而是放在緩沖區(qū)中,直到事件到之后丐吓,再將所有在這段緩沖事件內(nèi)放入緩沖區(qū)中的值宣羊,放在一個List
中一起發(fā)送到下游。
3.2 Buffer 的其它用法
關(guān)于Buffer
的其它用法汰蜘,這篇文章寫得很全仇冯,我這里就不詳細(xì)贅述了,大家可以參考:RxJava 的學(xué)習(xí)之變換操作符 - Buffer族操。
四苛坚、參考文獻(xiàn)
RxJava 的學(xué)習(xí)之變換操作符 - Buffer
更多文章,歡迎訪問我的 Android 知識梳理系列:
- Android 知識梳理目錄:http://www.reibang.com/p/fd82d18994ce
- 個人主頁:http://lizejun.cn
- 個人知識總結(jié)目錄:http://lizejun.cn/categories/