1, 概述
CountDownTimer从字面理解就是倒计时器,每隔固定的时候可以触发onTick方法,主要应用于倒计时和周期的执行特定的事情,控制灵活多变。
2, CountDownTimer
CountDownTimer是一个抽象类,有2个抽象方法, onTick和onFinish
public abstract void onTick(long millisUntilFinished);
public abstract void onFinish();
2.1 开发方法
首先实现CountDownTimer的2个抽象方法。需要重复执行放在onTick方法中
final int OUT_TIME = 21000; // 总的计数时间
final int SCAN_INTERVAL = 4000; // 间隔时间
CountDownTimer mCountDownTimer = new CountDownTimer(OUT_TIME, SCAN_INTERVAL) {
private int tickCount = 0;
@Override
public void onTick(long arg0) {
tickCount++;
•••
}
@Override
public void onFinish() { }
};
调用start方法开始倒计时
mCountDownTimer.start();
调用cancel方法终止倒计时
mCountDownTimer.cancel();
2.2 原理分析
CountDownTimer类很简单,有以下4个变量,
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;
}
start方法如下,
public synchronized final CountDownTimer start() {
mCancelled = false;
if (mMillisInFuture <= 0) {
onFinish();
return this;
}
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return this;
}
由此看到,其实现核心也是利用handler。
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
long delay = lastTickStart + mCountdownInterval - SystemClock.elapsedRealtime();
// special case: user's onTick took more than interval to
// complete, skip to next interval
while (delay < 0) delay += mCountdownInterval;
sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
};
主要逻辑如下,
1,首先判断是否是否终止,如果终止了就直接返回。
2,如果倒计时结束时间小于系统当前时间,说明应该结束倒计时,因此直接调用onFinish方法。
3,如果倒计时结束时间和系统当前时间之差间隔时间,直接发送延迟消息。
例如间隔时间为4s,时间差为3s,直接发送延时间为3s的消息。
下一个消息会走到情况2.
4,如果时间差大于间隔时间,直接调用onTick方法。变量delay是什么意思呢?
这样在调用onTick方法之前这样发送消息不行吗,
sendMessageDelayed(obtainMessage(MSG), mCountdownInterval);
如果onTick方法执行时间总是小于mCountdownInterval的,那么这样是可以的。
但是如果onTick方法执行时间大于mCountdownInterval,即delay小于0时,
这样会导致上一个onTick方法未执行完又接着调用onTick方法,有未知的风险。
源码这样写能保证上一个onTick方法执行完之后才接着调用下一个上一个onTick方法。
Cancel方法如下,
public synchronized final void cancel() {
mCancelled = true;
mHandler.removeMessages(MSG);
}
小结:
1, CountDownTimer使用简单,总的时间和间隔时间很灵活。
2,如果 onTick时间执行过长,最好将间隔时间设置长一点。
3,开发时,可以写一个有暂停,继续,和快进快退的倒计时器。