概述
//Handler中的源码
public final boolean postDelayed(Runnable r, long delayMillis)
{
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public final boolean postAtTime(Runnable r, long uptimeMillis)
{
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
上面的代码节选自Android的Handler源码。
postDelayed 和 postAtTime 这两个方法都是用来执行线程的。那么它们的相同点和不同点在哪呢?
小伙伴:相同的是它们最后都通过sendMessageAtTime方法来实现,不同的是postDelayed先调用的sendMessageDelayed方法,再调用的sendMessageAtTime方法去实现。
没错,那么在sendMessageDelayed方法中做了什么呢?为什么要通过这个方法中转呢?
小伙伴:在sendMessageDelayed方法中对delayMillis进行了判值操作,然后用delayMillis和SystemClock.uptimeMillis()的和作为参数去调用sendMessageAtTime方法。可是我也不知道为什么要这么做。。。
嘿嘿嘿,主要是因为sendMessageAtTime方法的时间计算基准是以系统唤醒时间为准的。所谓系统唤醒时间,我的上一篇博客已经写过了,没看过的小伙伴可以去看看 Android中的System.currentTimeMillis和SystemClock类
就是因为这个原因在Delayed(延迟)操作时需要以系统唤醒时间为准,以确定向后Delayed(延迟)多长时间。
举个例子:
当前的系统唤醒时间(System.currentTimeMillis)是:5000毫秒
那么我希望在4秒后执行一个线程A。那我可以怎么做呢?
小伙伴:可以通过postDelayed方法:postDelayed(Runnable A,4000)
没错,这样的确可以。那如果我希望线程A在开机后的5分钟执行呢?还能使用postDelayed方法吗?
小伙伴:额,不能使用postDelayed方法了。因为我们没法保证我们的APP可以跟随系统同时启动。
对的,那有啥办法解决这个问题吗?
小伙伴:结合你之前的博客中的例子,可以通过postAtTime方法来实现。
postAtTime方法正是以Android的系统唤醒时间为基准的。也就是说我们只需要
调用postAtTime(Runnable A, 5 * 60 * 1000)就可以实现了。
嗯,没错。但也存在一点问题。。。首先系统唤醒时间不代表开机到现在的时间。因为屏幕休眠、cpu休眠都会导致唤醒时间被暂停增长。所以一般来说系统唤醒时间是小于开机时间的。所以要想更准确的找到开机后的5分钟,需要搭配一下SystemClock类来处理。
首先计算出开机时间和唤醒时间的差值。
long temp = SystemClock.elapsedRealtime - SystemClock.uptimeMillis;
随后在5分钟的基础上减掉差值
postAtTime(Runnable A, (5 * 60 * 1000) - temp );
小伙伴:但是这样好像也不完美啊!不能保证唤醒时间在执行之前不发生变化呀!
对的没错。。。但是这样已经是比较简单的实现方式了。更上一层楼的方法是对SystemClock.elapsedRealtime进行监听。。。
当它抵达5分钟的时间点的时候执行线程。但是这样写成本就高了不少呀。。。只能是祈求不要遇到这么坑的需求
最后
以上就是愉快墨镜为你收集整理的Android Handler知识学习记录(一)Handler的postDelayed和postAtTime的全部内容,希望文章能够帮你解决Android Handler知识学习记录(一)Handler的postDelayed和postAtTime所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复