定时执行任务,大家都会想到timer或者thread,确实,这两者都能达到。
好吧,还是先说需求
自动每隔10秒执行一次任务,如果点击了某个按钮,则立即执行任务,并重新计时,也就是说从点击按钮开始再隔10秒才会执行任务。
用timer怎么实现?
我做不到,我不知道怎么修改timer的计时器
用thread怎么实现?
开一个线程,用一个变量记录这一次执行任务的时间(按按钮或者自动执行),一个while循环不断获取当前时间,如果满足10秒,执行,并修改执行任务的时间为当前时间;点击按钮,执行任务,并修改执行任务的时间为当前时间。
android中怎么做?
用android.os.CountDownTimer
CountDownTimer是在handler中进行逻辑处理的,主要是靠发送延迟消息来计时
CountDownTimer,会先判断距离剩余时间是否小于0,如果小于0,调用onfinish,如果在0~timeInterval之间,也会sendmessageDelay,也就是说,最后还会执行一次,
如果大于timeInterval,则逻辑处理,触发任务,sendmessageDelay.
里面有一点很有意思的代码 handler中的
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);
}
}
注意那个while循环 22 行,我第一眼还以为是这里为了延时的处理,后来一想,不对,handler是在主线程中的,主线程怎么能延时呢?
其实注释已经很清楚了,就是保证delay大于0。
可以说是一开始执行就计时,
执行前的时间 + 时间间隔 - 现在的时间 = 需要延时的时间
如果执行了很长时间,大于了间隔时间,那么得到的延时时间就是负数,这是不行的。
但是,用在需求上,这就不好做了,如果我们在timer结束的时候调用cancle再start,假设是参数是5000,3000,也就是说,会在3秒之后的2秒后cancle,再start,start会sendmessage,然后handler中进行任务触发,并sendmessageDelay,也就是说是隔了2秒就执行了
这不符合我们的需求,那么改一改源码
// 只要小于间隔时间,就不再执行任务
if (millisLeft < mCountdownInterval){
onFinish();
} else {
......
小于间隔,我们就onfinish,在onfinish中cancle,然后start
long time = System.currentTimeMillis();
Log.e("tag","time " + time);
// countDownTimer = new CountDownTimer(3000, 3000) {
countDownTimer = new CountTimer(3000, 3000) {
@Override
public void onTick(long millisUntilFinished) {
handler.sendEmptyMessage(1);
long time = System.currentTimeMillis();
Log.e("tag","time " + time);
}
@Override
public void onFinish() {
cancel();
start();
}
}.start();
建议 arg1 < arg0 < 2 * arg1
代码已上传
如果发现bug,或需要优化的地方,请及时告知
最后欢迎关注我的微信公众号:云端看大地