android中倒計時控件CountDownTimer分析 1 示例代碼 new CountDownTimer(10000, 1000) { public void onTick(long millisUntilFinished) { LogUtil.i(TAG, "seconds remaining: " + millisUntilFinished / 1000); } public void onFinish() { LogUtil.i(TAG, "done!"); } }.start(); 2 API解析 CountDownTimer (long millisInFuture, long countDownInterval) millisInFuture: 你要倒計時的總時間, 單位ms. countDownInterval: 你要倒計時的間隔時間, 單位ms. public final void cancel () //取消當前的任務 public abstract void onFinish () //當前任務完成的時候回調 public abstract void onTick (long millisUntilFinished) //當前任務每完成一次倒計時間隔時間時回調 public final CountDownTimer start () //開始當前的任務 3 源碼分析 public abstract class CountDownTimer { private final long mMillisInFuture; //倒計時的總時間 private final long mCountdownInterval; //倒計時的間隔時間 private long mStopTimeInFuture; private boolean mCancelled = false; //是否取消計時任務 //構造方法 public CountDownTimer(long millisInFuture, long countDownInterval) { mMillisInFuture = millisInFuture; mCountdownInterval = countDownInterval; } //取消倒計時 public synchronized final void cancel() { mCancelled = true; mHandler.removeMessages(MSG); } //開始倒計時 public synchronized final CountDownTimer start() { mCancelled = false; if (mMillisInFuture <= 0) { onFinish(); return this; } mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture; mHandler.sendMessage(mHandler.obtainMessage(MSG)); return this; } //按期會回調的方法 public abstract void onTick(long millisUntilFinished); //計時結束的回調方法 public abstract void onFinish(); private static final int MSG = 1; //CountDownTimer採用的是handler機制,經過sendMessageDelayed延遲發送一條message到主線程的looper中, //而後在自身中收到以後判斷剩餘時間,併發出相關回調,而後再次發出message的方式。 //取消倒計時,把任務從對MessageQueue中移除就行了。 private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { synchronized (CountDownTimer.this) { if (mCancelled) { return; } final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime(); //剩餘時間 if (millisLeft <= 0) { onFinish(); } else if (millisLeft < mCountdownInterval) { sendMessageDelayed(obtainMessage(MSG), millisLeft); } else { long lastTickStart = SystemClock.elapsedRealtime(); onTick(millisLeft); long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime(); while (delay < 0) delay += mCountdownInterval; sendMessageDelayed(obtainMessage(MSG), delay); } } } }; } 4 幾點注意 1 elapsedRealtime currentTimeMillis()區別 System.currentTimeMillis()獲取的是系統時間,是距離1970年1月1日開始計算的一個值; android.os.SystemClock.elapsedRealtime()獲取從設備boot後經歷的時間值。 System.currentTimeMillis()獲取當前日期有意義,如當前是xxxx年xx月xx時xx分xx秒xxx毫秒,這個值在系統設置中能夠更改的; 而SystemClock.elapsedRealtime()計算某個時間經歷了多長時間有意義,例如通話經歷了多長時間,這個值是系統設置無關。 可是Android源碼中計算通話時間是用System.currentTimeMillis()的,這個通常狀況下是沒有問題的。 可是若是有人在設備創建通話後修改系統時間,那麼通話結束後的時間值就不對了,日期日後調整個幾年,通話時間就會顯示有幾年的 2 sendMessageDelayed() boolean sendEmptyMessageDelayed (int what, long delayMillis) 在特定的時間delayMillis流逝後 發送一個僅包含有what的消息