Handler
多少次,迎着冷眼与嘲笑,从没有放弃过心中的理想
让歌词吹去心中所有不悦,怀着冷却的心去
讨论下Handler
简单来说,Handler被理解为了四个部分,Handler,Looper,Message以及MessageQueue。Handler用来发送消息和处理消息,Message是用来发送消息的载体,Message一多了就得有东西去对他进行存储,管理,这是就用到了MessageQueue了,消息队列用来存储待处理的Message信息,最后就是Looper了,如果使用默认的构造,就是使用的对应线程的Looper对象。大概到这里,脑子里应该是有一副图。有三个点,分别是Handler,Looper以及MessageQueue。在三条线上传输的东西就是Message对象。自我理解到此结束,还是好好整理下。
相关概念
分别来说说上面说到的四个主要的东西,Handler,Message,Looper和MessageQueue。稍微整理下官方解释。
- Handler
相关联信息 : 允许我们去发送和处理Message,并且Runnable对象也可以和线程的MessageQueue进行link。每一个Handler对象和一个线程以及这个线程的
MessageQueue
相关联。
作用 : 1. 将之后要执行的Message添加到消息队列中去;2.在子线程把需要在另一个线程执行的操作加入到消息队列中
- Looper
一个线程运行一个消息Looper,线程默认是没有消息Looper相关联的,调用
prepare
来运行这个loop,然后调用loop
来处理消息直到loop停止
- MessageQueue
低级类,保存要处理的消息列表。消息不能够被直接添加到消息队列,需要通过handler对象和Looper
- Message
被定义用来通过Handler来发送的数据对象。该对象包含两个额外的int类型和一个额外的object类型,方便我们来分配数据
对应关系:
每个线程只有一个Looper
每个MessageQueue由Looper管理,主线程创建会创建一个默认Looper,Looper的创建会自动创建一个MessageQueue。非主线程不会自动创建Looper。
观源码有感
- Handler ## sendMessage()
对于发送Message对象,最后会发给MessageQueue的enqueueMessage方法,通过一个节点去维护整个消息队列的消息
// Handler
public final boolean sendMessage(Message msg){
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis){
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
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);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
// 在入队列的时候,会指定target为当前Handler
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
Handler 发送消息最终会发给MessageQueue对象进行处理
//MessageQueue
boolean enqueueMessage(Message msg, long when) {
//检查是否有target或者当前Message是否正在被使用,此处省略
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) {
// 如果没有创建头结点,就创建一个头结点
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
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;
}
}
// 将Message进行插入
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;
}
MessageQueue的入队列操作通过一个链表进行维护。
- Handler ## handleMessage()
在Looper在loop的时候,如果Message持有Handler对象(使用obtain()方法创建),就会分发给对应的Handler的dispatchMessage()方法进行处理,dispatchMessage()方法又会分发给 handleMessage方法进行处理
// Handler
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
这里看到最关键的,handlerMessage方法,也就是调到了dispatchMessage方法就会再去调用handleMessage()方法。
//Looper
public static void loop() {
final Looper me = myLooper();
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
// Looper的死循环,用来处理消息,从队列当中获取
Message msg = queue.next(); // might block
if (msg == null) {
// 没有消息,就结束
return;
}
...
final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
final long traceTag = me.mTraceTag;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
final long end;
try {
// 发给对应的Handler进行处理
msg.target.dispatchMessage(msg);
end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
if (slowDispatchThresholdMs > 0) {
final long time = end - start;
if (time > slowDispatchThresholdMs) {
Slog.w(TAG, "Dispatch took " + time + "ms on "
+ Thread.currentThread().getName() + ", h=" +
msg.target + " cb=" + msg.callback + " msg=" + msg.what);
}
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
调查发现,Looper中的loop()方法会调用到dispatchMessage()方法。在上面msg.target.dispatchMessage()
方法进行消息的分发处理。其中,target也就是Handler对象,在入队列的时候会将对应的Handler加到target中,也可以通过obtain方法指定。
- 消息管理
对于消息的管理,通过MessageQueue来对消息进行存储,对于分发,是在Looper中进行的。因为消息队列是由一个头结点进行维护的,所以在Looper的loop方法中会有个死循环,检测到有Message,就会发给对应的Handler。入队列时也会指定对应的Handler,相当于是对上面的一个简单总结。