Handler机制在android开发中经常使用,一直没搞明白Handler,Looper,MessageQueue它们之间的关系,此次就从源码的角度分析一下
1. 简述
Looper负责创建MessageQueue,然后进入无限循环体中不断从MessageQueue取出消息,触发消息的分发处理,而Handler负责发送消息
2.源码分析
- Looper
主要就是prepare和loop方法
prepare()方法:
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
从上面看出ThreadLocal存储了Looper对象,而且此方法不能运行两次,否则抛出异常.
loop()方法:
>public static void loop() {
final Looper me = myLooper(); //获得Looper
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't
called on this thread.");
}
final MessageQueue queue = me.mQueue; //获得MessageQueue
// 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
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg); //分发处理消息
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();
}}
首先myLooper()从ThreadLocal中获取Looper对象,如果looper为null则抛出异常,也说明prepare()在loop()之前运行
>public static Looper myLooper() {
return sThreadLocal.get();
}
下一步是拿到MessageQueue,即me.Queue;
再进入开头所说的无限循环,取出消息msg;
最后就是msg.target.dispatchMessage(msg),分发处理,target就是Handler.
概括Looper作用:
- 与当前线程绑定,保证一个线程只会有一个Looper实例,同时一个Looper实例也只有一个MessageQueue。
- loop()方法,不断从MessageQueue中去取消息,交给消息的target属性的dispatchMessage去处理。
下面就该Handler发送消息了
- Handler
-
Handler与MessageQueue绑定
看Handler构造方法public Handler() { this(null, false); } public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }
通过Looper.myLooper()获取了当前线程保存的Looper实例,然后又获取了这个Looper实例中保存的MessageQueue(消息队列),这样就保证了handler的实例与我们Looper实例中MessageQueue关联上了
下面看发送消息的方法
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) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
nqueueMessage中首先为msg.target赋值为this,也就是把当前的handler作为msg的target属性。最终会调用queue的enqueueMessage的方法,也就是说handler发出的消息,最终会保存到消息队列中去。
现在已经很清楚了Looper会调用prepare()和loop()方法,在当前执行的线程中保存一个Looper实例,这个实例会保存一个MessageQueue对象,然后当前线程进入一个无限循环中去,不断从MessageQueue中读取Handler发来的消息。然后再回调创建这个消息的handler中的dispathMessage方法,下面我们赶快去看一看这个方法:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
可以看到调用了 handleMessage(msg)方法;
public void handleMessage(Message msg) {
}
这是一个空方法,因为消息的最终回调都是我们自己实现的,在handler中实现handleMessage();
好了,现在总结一下整个流程:
1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法。
-
Handler post
一般使用方法
mHandler.post(new Runnable()
{
@Override
public void run()
{
Log.e("TAG", Thread.currentThread().getName());
}
});
看输出结果,当前thread就是handler所在线程,并不会单独创建线程,看源码:public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); }
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
可以看到就是将runnable设置为msg.callback,下面和handler.sendMessage一样,最终到dispatchMessage:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
此时因msg.callback != null,所以直接执行handleCallback(msg);
private static void handleCallback(Message message) {
message.callback.run();
}
handleCallback()其实就只执行的Runnable的run方法,所以handler.post不会另开线程;
嗯,到此就全部结束了,相信对Handler,Looper,MessageQueue之间的关系都有了解了吧.
网友评论