1. 程式人生 > >藉助CountDownTimer類實現獲取驗證碼倒計時按鈕

藉助CountDownTimer類實現獲取驗證碼倒計時按鈕

    咱們中國人做事情講究吉利,我也不例外,所以就選今天這個良辰吉日來寫出自己的第一篇部落格文章吧!

一、引言

    我們經常在電視中看到發生衛星的場景,大家都知道會有人在喊倒計時“5,4,3,2,1,發射!”,這個時候衛星就點火發射了。其實這些都是已經在程式當中寫好了的,即使沒有人喊,也一樣會在那個時間發射。那麼這個倒計時功能在java中是哪一個類來實現的呢?這個類就是今天的主角CountDownTimer類。

二、CountDownTimer類介紹

    CountDownTimer類是一個抽象類,需要寫一個子類來繼承,如:

class TimeCount extends CountDownTimer {

        public TimeCount(long millisInFuture, long countDownInterval) {
            super(millisInFuture, countDownInterval);
        }

        @Override
        public void onTick(long millisUntilFinished) {
            mSend.setBackgroundColor(Color.parseColor("#B6B6D8"));
            mSend.setClickable(false);
            mSend.setText(millisUntilFinished / 1000 + " 秒後可重新發送");
        }

        @Override
        public void onFinish() {
            mSend.setText("重新獲取驗證碼");
            mSend.setClickable(true);
            mSend.setBackgroundColor(Color.parseColor("#4EB84A"));

        }
    }

    其中在構造方法中,引數millisInFuture代表設定倒計時的總時間(毫秒),引數countDownInterval代表設定每次減去的時間(毫秒)。onTick()方法是進行倒計時的時候開始執行的,onFinish()方法是倒計時結束之後執行的。

    另外,CountDownTimer類還有start()和cancle()兩個方法,呼叫start()方法會開始倒計時,呼叫cancle()方法取消當前任務。

三、實現倒計時按鈕

private TimeCount time;
private Button mSend;
@Override
    protected void onCreateView(Bundle savedInstanceState) {
        super.onCreateView(savedInstanceState);
        setContentView(R.layout.fragment_phone);
        mSend = (Button) findViewById(R.id.btn_send);
        time = new TimeCount(60000, 1000);
        mSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                phone = mEtPhone.getText().toString();
                if (TextUtils.isEmpty(phone)) {
                    CustomToast.showShortError(getApplicationContext(), "請輸入賬號");
                    return;
                }
                if (!CheckUtil.isPhoneLegal(phone)) {
                    CustomToast.showShortError(getApplicationContext(), "手機格式不合法");
                    return;
                }
                //傳送請求
                LoginHttpClient.getClient().sms(getApplicationContext(), phone, Constants.SMS_TYPE_MESSAGE, mScene, new ResponseListener<ResponseInfo>() {
                    @Override
                    public void onSuccess(ResponseInfo info) {
                        switch (info.errno) {
                            case Errno.OK:
                                Bundle bundle = new Bundle();
                                bundle.putString(Constants.BUNDLE_KEY_PHONE, phone);
                                bundle.putInt(Constants.BUNDLE_KEY_SCENE, mScene);
                                CustomToast.showShortComplete(getApplicationContext(), "簡訊驗證碼已傳送");
                                //開啟倒計時
                                time.start();
                                break;
                            case Errno.ACCOUNT_NOT_EXISTS:
                                CustomToast.showShortError(getApplicationContext(), "該使用者未註冊");
                                break;
                            default:
                                CustomToast.showShortError(getApplicationContext(), info.msg);
                                break;
                        }
                    }

                    @Override
                    public void onFail(Throwable throwable) {
                        CustomToast.showShortError(getApplicationContext(), "請稍後重試");
                    }
                });

            }
        });
 @Override
    public void onDestroy() {
        time.cancel();
        super.onDestroy();
    }

    當傳送請求時呼叫time.start()方法,開始倒計時60秒,並執行onTick()方法,改變button的樣式,60秒倒計時結束的時候呼叫onFinish()方法。注意:不呼叫time.start()方法的話是不會開啟倒計時的。在銷燬activity的時候,呼叫cancle()方法,以防止記憶體洩漏和出現如空指標等異常。

四、注意事項

    1、空指標:如果在activity或者fragment關閉銷燬的時候沒有呼叫cancle()方法,它的onTick()方法還是會繼續執行,這個時候UI控制元件都為空,不注意判斷的話很容易空指標。在重寫onFinish()方法的時候加上一句“cancle()”就可以一勞永逸地解決這個問題了。

    2、時間不是太準的問題:

    我們看CountDownTimer的原始碼可以看到,在執行onTick的方法時,google原始碼裡面減去了程式執行到這裡的時候所消耗的時間,這裡可以看出google程式碼的嚴謹。

final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

if (millisLeft <= 0) {
    onFinish();
} else if (millisLeft < mCountdownInterval) {
    // no tick, just delay until done
    sendMessageDelayed(obtainMessage(MSG), millisLeft);
}

    所以一開始倒計時的時間是59,這裡可以在構造方法裡面稍微加一點時間就可以解決如:

new CountDownTimer(60 * 1000+300, 1000)

五、結束語

總的來說CountDownTimer類是十分簡單、十分接地氣的,用起來也很順手。今天通過寫這篇文章我把CountDownTimer類又看了一遍,重新總結了一下,可謂收穫頗豐。那麼第一篇文章就到這裡吧,再見!ヾ( ̄▽ ̄)Bye~Bye~

參考: