Debounce
1.官方定義
only emit an item from an Observable if a particular timespan has passed without it emitting another item
The Debounce operator filters out items emitted by the source Observable that are rapidly followed by another emitted item.
2.API
public final Observable<T> debounce(long timeout, TimeUnit unit); // 默認執行線程 Schedulers.computation() public final Observable<T> debounce(long timeout, TimeUnit unit, Scheduler scheduler);
3.Android中使用場景
快速點擊按鈕,執行某個操作。
比如美團APP中的選擇套餐:由左圖的0份快速點擊到右圖的7份,然后根據選中份數計算總價。
4.代碼實現一
// NumberPickerView.java ... plusView.setOnClickListener(v - > { selectCount++; countTv.setText(selectCount + ""); onChangeListener.onChange(dealId, selectCount); // dealId為當前套餐的id }); public interface OnChangeListener { onChange(int dealId, int selectCount); }
// activity ... numberPickerView.setOnChangeListener((dealId, selcetCount) -> { calculateDealPrice(dealId, selectCount); }); private calculateDealPrice(int dealId, int selectCount) { ... // 計算價格 }
對於這種快速點擊,我們其實需要的是對第7次進行計算,中間的一系列暫存態是沒必要計算的,使用debounce來解決。
5.代碼實現二:增加debounce操作
RxView.clicks(plusView) .map(aVoid -> { selectCount++; countTv.setText(selectCount + ""); return selectCount; } .debounce(400, TimeUnit.MILLISECONDS)) .observeOn(AndroidSchedulers.mainThread()) .subcribe(count -> onChangeListener.onChange(dealId, selectCount), Throwable::printStackTrace);
缺點:
1.NumberPickerView依賴了 com.jakewharton.rxbinding:rxbinding:x.x.x
2.NumberPickerView中plusView被強制增加了400ms的debounce操作
5.代碼實現三:將debounce操作移出NumberPickerView
// NumberPickerView.java ... plusView.setOnClickListener(v - > { selectCount++; countTv.setText(selectCount + ""); onChangeListener.onChange(dealId, selectCount); // dealId為當前套餐的id });
// activity ... PublishSubject<SelectParams> subject = PublishSubject.create(); numberPickerView.setOnChangeListener((dealId, selectCount) -> { subject.onNext(new SelectParams(dealId, selectCount)); }); subject.debounce(400, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(selectParams -> calculateDealPrice(selectParams.dealId, selectParams.selectCount), Throwable::printStackTrace); class SelectParams { int dealId; int selectCount; SelectParams(int dealId, int selectCont) { this.dealId = dealId; this.selectCount = selectCount; } } private calculateDealPrice(int dealId, int selectCount) { ... // 計算價格 }
此時NumberPickerView不再依賴第三方庫,適用性提高。
參考:http://reactivex.io/documentation/operators.html