藉助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~
參考: