Handler、Looper、MessageQueue作用与分工
- Handler:负责发送消息(sendMessage(Message) 或post(Runnale))并处理接受到消息
- Looper:负责轮询消息队列(MessageQueue)并取出消息回传给Hanlder
- MessageQueue:负责消息的存储,主要操作有消息的插入(enqueueMessage())与读取next()。
接下来分析从Hnadler初始化到处理消息handleMessage中整个过程是怎么回事
一. 创建Handler,Handler mHandler=new Handler(),做了哪些操作???
- 能得到两个重要信息点,一个通过Looper.myLooper()获取当前线程的Looper对象,另外一个就是获取MessageQueue对象;起初你可能会有疑问,Looper和MessageQueue是什么时候创建的,接下来看源码:
- ThreadLocal(类似HashMap,根据key取value)根据当前线程,取出同一线程对应的Looper对象。在获取Looper对象之前可能sThreadLocal没有Looper存储值是一个空对象,要先调用Looper.prepare()对它进行初始化。ThreadLocal其实是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获取存储的数据,对于其他线程则无法获取到数据,可以从ThreadLocal源码看出,提供了set和get方法。
上面提到了在sThreadLocal.get()获取Looper对象之前,必须先调用Looper.prepare()对它进行初始化,否则抛出Can’t create handler inside thread that has not called Looper.prepare()异常,如下:
private class DownloadThread extends Thread{
@Override
public void run() {
super.run();
//Looper.prepare();
Handler handler = new Handler();
handler.sendMessage(Message.obtain());
}
}
接下Looper.prepare()看看做了哪些操作!!!
- 从源码可以看出,在Looper的构造方法中它会创建一个MessageQueue即消息队列,然后将当前线程的对象保存起来。
接下来只剩Looper.prepare()这个何时调用了,是个疑问??都说Handler的使用必须调用此函数,在我们开发中并没有使用该函数,,其实在我们应用程序一启动入口时,系统默认创建了主线程,与此同时,在程序入口就已经帮我们初始化了Looper对象,我们可以ActivityThread这个类中发现
Looper最重要的一个方法就是loop,相当于MessageQueue中一把钥匙,只有调用了该方法,才能打开MessageQueue这把锁,消息循环系统才会起相应的作用,源码:
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
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 (;;) {
Message msg = queue.next(); // might block
//当消息从消息队列取出为空时,循环会结束
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
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 {
//msg.target是发送消息的对象Handler,由此可知Handler发送消息的任务在此交给了dispatchMessage来处理分发到主线程。
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();
}
}
接下来看看Handler的sendMessage方法,就是把Message对象插入消息队列中
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
//将消息对象Message,插入消息队列中
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) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
经过上面的分析,基本知道Handler、Looper、MessageQueue这三者关系
在创建Handler之前,必须初始化Looper对象(Looper.prepare)并保存当前线程,一个线程对应一个Looper对象;接下来Handler通过sendMessage方法发送消息,会向MessageQueue消息队列插入一条消息,然后Looper调用loop方法遍历是否有新消息,当接受到新消息时,会交由Handler对象处理,Handler会调用dispatchMessage方法将消息分发出去到主线程,最后调用Handler的handleMessage方法处理消息。