Android API自带的"计时"类,简单分析源码
1、CountDownTimer的启动:
/**
* Start the countdown.
*/
public synchronized final CountDownTimer start() {
//开关,每次start必须确保开关是打开状态
mCancelled = false;
//总时间不能小于0
if (mMillisInFuture <= 0) {
//结束的回调函数
onFinish();
return this;
}
//结束时间为当前时间+总时间
mStopTimeInFuture = SystemClock.elapsedRealtime() + mMillisInFuture;
//发送消息
mHandler.sendMessage(mHandler.obtainMessage(MSG));
return this;
}
2、Handler 接收消息
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
//线程锁,多线程操作可能会导致millisLeft 的差异
synchronized (CountDownTimer.this) {
//开关为关闭状态
if (mCancelled) {
return;
}
final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
if (millisLeft <= 0) {
onFinish();
//mCountdownInterval为计时的时间间隔
} 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 最后回调一次onTick
while (delay < 0) delay += mCountdownInterval;
sendMessageDelayed(obtainMessage(MSG), delay);
}
}
}
};
3、取消计时:
public synchronized final void cancel() {
mCancelled = true;
mHandler.removeMessages(MSG);
}
为何取消的时候handleMessage不执行onFinish()呢?
理当加上啊..
4、关于SystemClock
常用的API;
SystemClock.currentThreadTimeMillis();//1970 00:00:00到现在过去的毫秒数
SystemClock.elapsedRealtime();//手机从启动到现在的运行时间,且包括系统sleep(CPU关闭)的时间
SystemClock.uptimeMillis();//手机从启动到现在的运行时间,且不包括系统sleep(CPU关闭)的时间
5、小结
完全使用的Handler机制,未另外开辟新的线程或者Timer,延迟间隔时间后sendMessages,handler收到消息后继续sendMessages,简单的递归,很巧妙,用法自定义View里面很常见。