天天看點

倒計時CountDownTimer 源碼分析

CountDownTimer 是 android sdk中os包下的一個 抽象類 這個類是通過handler來實作一個倒計時的操作。在倒計時期間會定期調用使用者實作的回調函數。拿來用作倒計時非常友善。

1、首先看一下如何使用

public class MyCountDownTimer extends CountDownTimer {

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

    @Override
    public void onTick(long millisUntilFinished) {
    }

    @Override
    public void onFinish() {
        setAlpha(toAlpha);
    }
}
           

來一個5s倒計時

倒計時總時間5000ms,500ms回調一次方法。

countDownTimer = new MyCountDownTimer(5000, 500);
        countDownTimer.start();
           

 2、分析源碼   CountDownTime 的構造函數 millisInFuture 是從調用start方法開始直到倒計時結束的毫秒時間,countDownInterval 是接收onTick回調的時間間隔。

/**
 * Start the countdown.
 */
public synchronized final CountDownTimer start() {
    mCancelled = false;//是否取消
    if (mMillisInFuture <= 0) {
        onFinish();
        return this;
    }
    mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture; //結束倒計時的時間
    mHandler.sendMessage(mHandler.obtainMessage(MSG));
    return this;
}
           

開始倒計時

/**
 * Start the countdown.
 */
public synchronized final CountDownTimer start() {
    mCancelled = false;//是否取消
    if (mMillisInFuture <= 0) {
        onFinish();
        return this;
    }
    mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture; //結束倒計時的時間
    mHandler.sendMessage(mHandler.obtainMessage(MSG));
    return this;
}
           

取消倒計時

/**
 * Cancel the countdown.
 */
public synchronized final void cancel() {
    mCancelled = true;
    mHandler.removeMessages(MSG);
}
           

定期會回調的方法

/**
 * Callback fired on regular interval.
 * @param millisUntilFinished 剩餘時間
 */
public abstract void onTick(long millisUntilFinished);
           

計時結束的回調方法

/**
 * Callback fired when the time is up.
 */
public abstract void onFinish();
           

下面看一下處理及時的 mHandler

// handles counting down
    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) {
                    // no tick, just delay until done
                    sendMessageDelayed(obtainMessage(MSG), millisLeft);// 剩餘時間小于一次時間間隔的時候,不再通知,隻是延遲一下

                } else {
                    long lastTickStart = SystemClock.elapsedRealtime();
                    onTick(millisLeft);

                    // take into account user's onTick taking time to execute
		//延時時間減去onTick()處理的時間
                    long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();

                    // special case: user's onTick took more than interval to
                    // complete, skip to next interval
		 // 特殊情況:使用者的onTick方法花費的時間比mCountdownInterval長,那麼直接跳轉到下一次mCountdownInterval

                    while (delay < 0) delay += mCountdownInterval;

                    sendMessageDelayed(obtainMessage(MSG), delay);
                }
            }
        }
    };
           

CountDownTimer采用的是handler機制,通過sendMessageDelayed延遲發送一條message到主線程的looper中,然後在自身中收到之後判斷剩餘時間,并發出相關回調,然後再次發出message的方式。取消倒計時,把任務從對MessageQueue中移除就好了。

繼續閱讀