天天看点

倒计时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中移除就好了。

继续阅读