前言
做開發的一定就會碰到測試提這樣的問題:“我快速地點擊這里,怎么就 XXX 了啊!”,一般,我們的開發情景是考慮用戶單擊或者雙擊了按鈕,我們沒有想到一個“帕金森式”的瘋狂點擊情景,就會出現這樣 Bug 了,那么,今天我就提供一種避免“帕金森”問題的解決思路。
優雅的解決方式
我們 Coder、Programmer 最要緊的就是優雅,所以網上查詢得到的繁瑣的方法這里就不贅述了,直接上最優雅的(其實你們如果用上了 RxBinding,這里可以變得更美妙)
以基本 View 的 onClick 方法為例
我們可以自定義一個 NoDoubleClickListener
public abstract class NoDoubleClickListener implements View.OnClickListener {
protected static final String TAG = "NoDoubleClickListener";
private static final int MIN_CLICK_DELAY_TIME = 1000;
private long lastClickTime = 0;
abstract void onNoDoubleClick(View v);
@Override
public void onClick(View v) {
long currentTime = SystemClock.uptimeMillis();
if (currentTime - lastClickTime > MIN_CLICK_DELAY_TIME) {
lastClickTime = currentTime;
onNoDoubleClick(v);
}
}
}
使用方法—— 給submitButton設置點擊事件時用NoDoubleClickListener代替OnClickListener,并且實現方法onNoDoubleClick代替onClick即可,像這樣:
submitButton.setOnClickListener(new NoDoubleClickListener() {
@Override
public void onNoDoubleClick(View v) {
submitOrder();
}
});
很簡單,見代碼……
就是用onNoDoubleClick代替onClick處理具體的操作,在onClick方法中加一個判斷:在接收到點擊事件之后,先判斷一下時間,如果距離上次處理操作不足MIN_CLICK_DELAY_TIME,就忽視——即能防止誤操作的連續點擊導致重復事件。
MIN_CLICK_DELAY_TIME可調。
優勢
好處是不用改變原有代碼的邏輯,就只需要兩個替換:NoDoubleClickListener代替OnClickListener,onNoDoubleClick代替onClick。 代碼的結構等都不需要做改變,不需要關心處理更改button的狀態這些額外判斷邏輯,只需要關注業務邏輯即可,簡潔優雅~
RxBinding
好,回到了我們說的如果使用 RxBinding 可以做到更優雅的解決方案,我們就具體來看那看怎么實現,show me the code。
Button button = ...;
RxView.clickEvents(button) // 以 Observable 形式來反饋點擊事件
.throttleFirst(500, TimeUnit.MILLISECONDS)
.subscribe(new Action1<ViewClickEvent>() {
@Override
public void call(ViewClickEvent event) {
// Click handling
}
});
優勢
RxBinding 不僅能在這里饒有作為,但也并不局限于此,具體可以查看它的 GitHub 倉庫
劣勢
如果是項目開發的后期,才想到要做這種修改,那改動量未免有點太大了些。