CountDownTimer

  • 简介:
    倒计时类,提供倒计时服务,只需提供总的倒计时时间和每次的间隔,就会定时收到回调;
    比如:
    倒计时30s,每秒收到一个回调,结束时也收到回调
 * new CountDownTimer(30000, 1000) {
 *
 *     public void onTick(long millisUntilFinished) {
 *         mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
 *     }
 *
 *     public void onFinish() {
 *         mTextField.setText("done!");
 *     }
 *  }.start();

其中2个回调是暴露接口

public abstract void onTick(long millisUntilFinished);
public abstract void onFinish();

  • 源码解析
  1. 构造函数得到初始化参数
  2. start方法启动定时器,触发handler消息循环
  3. handler逻辑,不停的计算回调
构造函数 及初始化变量
 // 倒计时总时间
private final long mMillisInFuture;
 //回调时间间隔
private final long mCountdownInterval;
 // 倒计时截止时刻,由mMillisInFuture计算得到
private long mStopTimeInFuture;
// 取消倒计时标志位
private boolean mCancelled = false;
    public CountDownTimer(long millisInFuture, long countDownInterval) {
        mMillisInFuture = millisInFuture;
        mCountdownInterval = countDownInterval;
    }
开始倒计时
    public synchronized final CountDownTimer start() {
        mCancelled = false;
        if (mMillisInFuture <= 0) {
            onFinish();
            return this;
        }
        // 倒计时截止时刻
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
       // handler 开启消息循环处理
        mHandler.sendMessage(mHandler.obtainMessage(MSG));
        return this;
    }
关键的handler来负责倒计时时间计算和回调
    // handles counting down
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            synchronized (CountDownTimer.this) {
                if (mCancelled) {
                    return;
                }

         // 1. 计算 剩余总时间
                final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();

                if (millisLeft <= 0) {
                    onFinish();
                } else {
                    long lastTickStart = SystemClock.elapsedRealtime();
                    onTick(millisLeft);

                    // take into account user's onTick taking time to execute
                    long lastTickDuration = SystemClock.elapsedRealtime() - lastTickStart;
                    long delay;

                    // 如果剩余总时间还不足以一个时间间隔,就直接delay剩余时间   --》 onFinish
                    if (millisLeft < mCountdownInterval) {
                        // just delay until done
                        delay = millisLeft - lastTickDuration;

                        // special case: user's onTick took more than interval to
                        // complete, trigger onFinish without delay
                        if (delay < 0) delay = 0;
                    } else {
                        delay = mCountdownInterval - lastTickDuration;

                        // special case: user's onTick took more than interval to
                        // complete, skip to next interval
                        while (delay < 0) delay += mCountdownInterval;
                    }

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

逻辑还是比较清晰的,要考虑各种容错,比如剩余时间的正负,剩余时间是否够一个时间间隔,以及 onTick的执行时间;(如果onTick消耗时间过多,超过了一个时间间隔,就直接略过),必须保证delay为正!
流程大约为:

  1. 计算剩余总时间,若<=0,则finish;
  2. 回调onTick,并记录onTick耗时
  3. 剩余总时间小于一个时间间隔 ,则延迟这部分时间(减去onTick耗时)(保证为正)--》finish
  4. 剩余总时间大于一个时间间隔,则以一个时间间隔减去onTick耗时作为延迟时间 --》onTick

      if (mCancelled) {
          return;
      }

可知取消倒计时只需要设置mCancelled即可

    public synchronized final void cancel() {
        mCancelled = true;
        mHandler.removeMessages(MSG);
    }

你可能感兴趣的:(CountDownTimer)