handler有时会使用
post和postDelayed方法去执行一些任务,这里就从这两个方法去看一下hanlder在执行这两个方法的时候都做了什么
handler的post方法最终调用的是sendMessageDelayed,而handler的postDelayed方法(不管是三个参数还是两个参数的都会)最终也会调用到sendMessageDelayed方法当中。
sendMessageDelayed的方法里面会首先判断当前是否有消息队列(MessageQueue),如果为null则抛出异常。没有的话就去执行enqueueMessage方法。
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
enqueueMessage方法在MessageQueue当中,方法进来之后会首先判断message的target和isinuse。
如果target不为null,isInUser不为true的话就会进入到同步锁的代码块当中(这里之所以加锁以我目前的拙见是因为这个方法会被handler多次调用有多线程的情况,暂时没有找到代码块可以佐证这个想法),进来之后会首先判断mQuitting的状态,该变量只有在退出消息队列的时候才会置为true(布尔值在声明的时候如果没有设置过值,默认值为false)。
不为true之后,就会走到后面的判断。大家可以看到第一个判断,有三个判断条件。分别判断的是message是空的,时间是否为0,时间是否小于message的时间。
如果符合这个判断条件的话,就会把传递过来的message赋值给当前的message然后传递出去。
如果不符合第一个判断的条件就会进入到else里面。
咱们先看一下代码里面的这块注释的大概意思,
可以看到这里说明了这部分会把消息插入到队列当中,直到消息在消息队列的头部。
这里有一个for循环,会循环获取消息,判断消息的状态。直到消息为null或者时间小于消息的设定时间,才会退出此循环(之前印象当中跟我说handler里面有一个无限for循环,看来其实是在消息队列里面)。从这个流程就可以看出消息通过post和postDelayed这两个方法的执行过程是怎么走的了。