Handler是什么?
Handler在我们android开发中是一项非常重要的机制,那Handler是什么呢?Handler是android提供用于更新UI的一套机制,也是消息处理机制。
Handler重要的四个类:
handler (处理器类):用来发送消息和处理消息。
looper(循环类):通过loop(for死循环)查看当前的消息链表中是否有需要处理的message。
messagequeue(消息队列类):用来存储message的链表(链表中的消息message是按when(当前系统的时间戳)从小到大的排列)。
message(消息类):用来存储消息内容。
那么如何将这几个类串联起来呢?
通过handler.sendMessage这个方法,把当前的消息对象message传入到handler中,通过handler中的messagequeue对象的引用(通过在handler的构造函数中,用looper获取到的),把Message放入到MessageQueue中。在message存放的时候,message对象的target属性记录了当前的handler。message通过消息的执行时间when,从小到大排列插入到消息链表中。我们looper的loop方法中的for(死循环)去查看当前的MessageQueue链表中是否有需要执行的Message。通过Message的when(消息的执行时间判断)和当前的系统时间戳做对比,如果当前的系统时间戳小于当前messagequeue链表中的消息执行时间,当前的执行进入等待状态。(管道机制,nativepollonce)如果当前的系统时间戳大于或等于当前的MessageQueue链表中的消息执行时间,我们就把当前的message从消息链表中删除,并且把该消息返回给Looper的loop方法中。在loop方法中获取到message以后判断message所对应的target(也就是发送message的handler)是否存在,如果存在就调用target.dispathMessage方法把当前的message传入,在dispathMessage方法中,我们将调用handleMessage这个方法。把当前取出的message传出去。这样在我们handler中重写的handleMessage就拿到了当前处理的消息。
消息队列中的消息如何排队?
boolean enqueueMessage(Message msg, long when) {
synchronized (this) {
//将消息执行的绝对时间存储起来
msg.when = when;
//msg2 : p = msg1
//msg3: p = msg1
//msg4: p = msg1
//msg5: p = msg4
Message p = mMessages;
//排序原理:每次新的消息进来,都是和队首消息比较,
//1.如果比队首执行早,那么当前消息到队首
//2.如果比队首晚,和队首的下一个(B)比较,如果比B还晚,再和B。next (C) 比较。。。。
if (p == null || when == 0 || when < p.when) {
//1.发现哪个消息可以进来??比队首还要早执行的消息,当前消息应该是队首消息,并且保存成功成员变量
// New head, wake up the event queue if blocked.
//msg1: msg1.next = p = null
//msg4:msg4.next = msg1
msg.next = p;
//msg1:mMessages = msg1
//msg4:mMessages = msg4;
mMessages = msg;
} else {
//2.能走到这个分支,说明当前消息肯定比队首消息执行晚,会从队首消息的下一个消息开始比较,直到找到合适的位置位置
Message prev;
for (;;) {
//msg2:prev = p = msg1(1000)(队首msg)
//msg3:prev = p = msg1(队首msg)
//msg5:prev = p = msg4(队首msg)
prev = p;
//msg2:p = p.next = msg1.next = null;
//msg3:p = msg1.next = msg2;
//msg5: p = p.next = msg1(和队首消息的下一个消息进行比较)
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
//msg2:msg2.next = p = null
//msg3: msg3.next = msg2
msg.next = p; // invariant: p == prev.next
//msg2:prev.next = msg1.next = msg = msg2
//msg3:msg1.next = msg3
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}