1. 程式人生 > >Android 防止多次點選

Android 防止多次點選

問題

onClick()事件是Android中常見的回撥事件,正常情況下在很短的時間內我們只會點選一次Button,但不排除某些神經質的使用者連續瘋狂的按,那麼問題來了……

舉個簡單的例子,當我們在訂單頁面,正常點選後啟動支付Activity,但不小心在短時間內多次點選按鈕(可能是使用者手機比較卡頓),啟動了多個結算頁面,使用者支付完成後又回到訂單頁面,什麼鬼?(我要解除安裝了)

   btnPay.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick
(View v) { startPay(); } });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

那麼我們可以在點選後執行如下操作:

方法一:

  btnPay.setClickable(false);
  或
  btnPay.setEnabled(false);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

但是如果跳轉頁面失敗呢(這裡會涉及到網路請求),又要將按鈕設定為true,太麻煩了(一個大型專案有多少個按鈕,這得多增加多少行程式碼,我們的工資又不是按照行來結算的)

方法二:

我們自定義一個NoDoubleClickListener,繼承自OnClickListener:

public abstract class NoDoubleClickListener implements View.OnClickListener {
    public static final int MIN_CLICK_DELAY_TIME = 1000;
    private long lastClickTime = 0;

    @Override
    public void onClick(View v) {
        long currentTime = Calendar.getInstance().getTimeInMillis();
        if (currentTime - lastClickTime > MIN_CLICK_DELAY_TIME) {
            lastClickTime = currentTime;
            onNoDoubleClick(v);
        }
    }

    protected
abstract void onNoDoubleClick(View v); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在設定點選事件時用NoDoubleClickListener替換OnClickListener,並且實現方法onNoDoubleClick替換onClick即可:

  btnPay.setOnClickListener(new NoDoubleClickListener() {
          @Override
          protected void onNoDoubleClick(View v) {
              startPay();
          }
      });

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

原理很簡單,就不解釋了,這其實就是一個簡單的回撥功能。

方法三:我們優雅一點,使用throttleFirst操作符來解決按鈕被多次點選的問題,當然這涉及到RxJava了,這也是大勢所趨~~~

這裡寫圖片描述

 RxView.clicks(btnPay)
                .throttleFirst(1, TimeUnit.SECONDS)
                .subscribe(new Observer<Object>() {
                    @Override
                    public void onCompleted() {
                       //
                    }

                    @Override
                    public void onError(Throwable e) {
                        //
                    }

                    @Override
                    public void onNext(Object o) {
                        //
                    }
                });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

總結:

第二種方法已經優雅了許多,但還是覺得麻煩,RxJava那種簡潔的鏈式呼叫,配合Retrolambda的使用,越看越舒心。