首先我们来看一下Google官方实例代码。如下:
class LooperThread extends Thread
{
public Handler mHandler;
public void run()
{
Looper.prepare();
mHandler = new Handler()
{
public void handleMessage(Message msg)
{
// process incoming messages here
};
}
Looper.loop();
}
}
从中我们可以看出有以下几种对象:Thread 、Handler、Message以及Looper。让我们一个一个来分析。
首先,有一个线程LooperThread,它是Handler的执行场所。如图:
然后执行Looper.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));
}
而sThreadLocal是ThreadLocal<Looper>的实例。
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
原来调用Looper.prepare()方法后系统内部帮我们new了一个Looper,并且把这个Looper实例放入sThreadLocal中,从而保证这个Looper是当前线程唯一的。so 我们就有了一个唯一的Looper实例。如图:
既然有了实例,那我们接着看下Looper的构造方法,看看里面做了什么。
private Looper(boolean quitAllowed)
{
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
原来在构造方法里面又new了一个MessageQueue实例,从名字上来看,可能是一个存放Message的队列,既然是队列,所以它是先进先出(FIFO—first in first out)的。接着画图:
可以看出调用Looper.prepare()方法后,系统帮我们创建了Looper和MessqgeQueue实例,可以分别通过Looper.myLooper()和mLooper.mQueue获得对应的实例。
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static @Nullable Looper myLooper()
{
return sThreadLocal.get();
}
...
final MessageQueue mQueue;
...
Looper.prepare()的分析暂时到这里。我们接着看下面,下面我们new了一个Handler实例,先看Handler构造方法(省略其他,最后调用的是下面这个构造方法)。
public Handler(Callback callback, boolean async)
{
...
mLooper = Looper.myLooper();
if (mLooper == null)
{
throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
...
}
可以看到在Handler的构造方法里面初始化了Looper和MessageQueue对象,并且回调了handleMessage方法。如图:
我们接着往下看,执行Looper.loop()方法。看一下Looper.loop方法的源码:
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
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;
}
...
}
msg.target.dispatchMessage(msg);
...
}
首先拿到Looper的MessageQueue对象,无限循环(利用for(;;))取出MessageQueue里面的Message对象(果然MessageQueue里面放的的Message,哈哈)。取出以后调用msg.target.dispatchMessage(msg)方法。那么这个msg.target是个什么东东?看下Messqge的源码:
...
/*package*/ Bundle data;
/*package*/ Handler target;
/*package*/ Runnable callback;
...
原来是Handler,其实是调用了Handler.dispatchMessage(msg)方法。还记得我们初始化Handler的时候回调了handleMessage(msg)方法吗?我们大胆的猜想下,会不会在dispatchMessage(msg)里面调用了handleMessage(msg)?看下Handler.dispatchMessage(msg)方法源码:
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg)
{
if (msg.callback != null)
{
handleCallback(msg);
} else
{
if (mCallback != null)
{
if (mCallback.handleMessage(msg))
{
return;
}
}
handleMessage(msg);
}
}
哈哈,果然调用了 handleMessage(msg)方法(这B装的太假了。。。)。
原来Looper.loop()方法就是在不停的取出MessageQueue里面的Message对象,并且执行handleMessage(msg)方法,所以初始化Handler的那个handleMessage回调会在这时候被调用。看图(表吐槽。。。):
那么问题来了:
1,Message是怎么创建的?
2,MessageQueue里面的Message对象是怎么放进去的呢(从图中可以猜出是Handler放进去的)?
3,Handler是怎么赋值给msg.target的?。
我们回想下我们使用Handler的使用。
...
mHandler.sendEmptyMessage(0x01);
...
看下Handler的sendEmptyMessage源码:
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
}
接着走Handler的sendEmptyMessageDelayed方法。
public final boolean sendEmptyMessageDelayed(int what, long delayMillis)
{
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
原来Message对象在这时候被创建了,解决了问题1。再往下看Handler的sendMessageDelayed方法。
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);
}
终于出现MessageQueue对象了,是不是要放入Message到 MessageQueue 里面呢?接着看。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)
{
msg.target = this;
if (mAsynchronous)
{
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
haha, msg.target = this,这个this是当前的Handler对象,原来在这里把Handler对象赋值给msg.target,解决问题3,接着看MessageQueen的enqueueMessage方法:
boolean enqueueMessage(Message msg, long when)
{
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;
}
...
}
其中有一句mMessages = msg。mMessages 保存的是当前消息队列,如果它为空就把消息添加到消息队列头,否则就要找到合适的位置将当前消息添加到消息队列。还记得Message是怎么取出来的吗(在Looper.loop方法里Message msg = queue.next(); )?看下queue.next()方法:
...
Message next() {
synchronized (this)
{
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null)
{
// Stalled by a barrier. Find the next asynchronous message in the queue.
do
{
prevMsg = msg;
msg = msg.next;
}while (msg != null && !msg.isAsynchronous());
}
if (msg != null)
{
if (now < msg.when)
{
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else
{
// Got a message.
mBlocked = false;
if (prevMsg != null)
{
prevMsg.next = msg.next;
} else
{
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg); msg.markInUse();
return msg;
}
...
}
...
其中省去了许多代码,想看的同学可以自己去看看下。最后会返回找到的msg(其中没有分析msg.next还有msg.isAsynchronous),而Message msg = mMessages,所以在enqueueMessage里面被赋值的mMessages就被返回给了Looper.loop()里面的msg,紧接着回调msg.target.dispatchMessage()方法。这样所有的都关联起来了,大功告成。最后来张图:
总结
1,1个线程有且只有一个Looper,在Looper里有且只有一个MessageQueue,这些对象的初始化都是在Looper.prepare()方法完成。
2,Handler往MessageQueue里面利用sendMessage方法添加Message,Looper利用Looper.loop()方法取出Message,并且回调msg.target.dispatchMessage方法.
3,在线程里必须调用一次Looper.prepare()和Looper.loop()方法。
4,主线程中怎么没见调用3中的2个方法?因为系统帮我们调用了。
(ps:由于第一次写简书,而且笔者水平有限,文中可能出现错误的地方,希望多多保函和指正。)