Handler、Looper與MessageQueue源碼分析
在Android中可以通過(guò)Handler來(lái)更新主線程中UI的變化,更新UI只能在主線程中進(jìn)行更新,而為了讓其他線程也能控制UI的變化,Android提供了一種機(jī)制Handler、Looper與MessageQueue一同協(xié)作來(lái)達(dá)到其他線程更新UI的目的。
一般我們會(huì)在主線程中通過(guò)如下方法定義一個(gè)Handler
- private Handler mHandler = new Handler() {
 - @Override
 - public void handleMessage(Message msg) {
 - tv.setText("mHandler change UI");
 - super.handleMessage(msg);
 - }
 - };
 
一般都見(jiàn)不到Looper與MessageQueue的,那么它們都是在哪里調(diào)用與如何協(xié)作的呢?在主線程不會(huì)顯式的調(diào)用Looper而是會(huì)在ActivityThread.main方法中默認(rèn)調(diào)用。
- public static void main(String[] args) {
 - Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
 - SamplingProfilerIntegration.start();
 - // CloseGuard defaults to true and can be quite spammy. We
 - // disable it here, but selectively enable it later (via
 - // StrictMode) on debug builds, but using DropBox, not logs.
 - CloseGuard.setEnabled(false);
 - Environment.initForCurrentUser();
 - // Set the reporter for event logging in libcore
 - EventLogger.setReporter(new EventLoggingReporter());
 - // Make sure TrustedCertificateStore looks in the right place for CA certificates
 - final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
 - TrustedCertificateStore.setDefaultUserDirectory(configDir);
 - Process.setArgV0("<pre-initialized>");
 - Looper.prepareMainLooper();//創(chuàng)建Looper
 - ActivityThread thread = new ActivityThread();
 - thread.attach(false);
 - if (sMainThreadHandler == null) {
 - sMainThreadHandler = thread.getHandler();
 - }
 - if (false) {
 - Looper.myLooper().setMessageLogging(new
 - LogPrinter(Log.DEBUG, "ActivityThread"));
 - }
 - // End of event ActivityThreadMain.
 - Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 - Looper.loop();//開(kāi)啟Looper循環(huán)
 - throw new RuntimeException("Main thread loop unexpectedly exited");
 - }
 
如上代碼,調(diào)用了Looper.prepareMainLooper()方法,在主線程中創(chuàng)建了一個(gè)Looper,不信的話我們?cè)俨榭丛摲椒ㄗ隽耸裁?/p>
Looper
prepare
- public static void prepare() {
 - prepare(true);
 - }
 - 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));//創(chuàng)建Looper并賦給sThreadLocal
 - }
 - /**
 - * Initialize the current thread as a looper, marking it as an
 - * application's main looper. The main looper for your application
 - * is created by the Android environment, so you should never need
 - * to call this function yourself. See also: {@link #prepare()}
 - */
 - public static void prepareMainLooper() {
 - prepare(false);
 - synchronized (Looper.class) {
 - if (sMainLooper != null) {
 - throw new IllegalStateException("The main Looper has already been prepared.");
 - }
 - sMainLooper = myLooper();
 - }
 - }
 - public static @Nullable Looper myLooper() {
 - return sThreadLocal.get();
 - }
 
在prepareMainLooper方法中調(diào)用了prepare而通過(guò)prepare會(huì)發(fā)現(xiàn)它其實(shí)就是創(chuàng)建了一個(gè)Looper,并把它賦給了sThreadLocal。同時(shí)可以通過(guò)myLooper方法獲取當(dāng)前線程中的Looper。再來(lái)看下new Looper(quitAllowed)初始化了什么
- private Looper(boolean quitAllowed) {
 - mQueue = new MessageQueue(quitAllowed);
 - mThread = Thread.currentThread();
 - }
 
在這里我們終于看到了MessageQueue了,它創(chuàng)建了一個(gè)MessageQueue。該消息隊(duì)列就是用來(lái)保存后續(xù)的Message。再回到ActivityThread.main方法中,發(fā)現(xiàn)它調(diào)用了Looper.loop()是用來(lái)開(kāi)啟Looper循環(huán)的,監(jiān)聽(tīng)消息隊(duì)列MessageQueue中的消息。
loop
我們來(lái)看下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;//獲取消息隊(duì)列
 - // 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 traceTag = me.mTraceTag;
 - if (traceTag != 0) {
 - Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
 - }
 - try {
 - msg.target.dispatchMessage(msg);//通過(guò)Handler分發(fā)消息
 - } finally {
 - if (traceTag != 0) {
 - Trace.traceEnd(traceTag);
 - }
 - }
 - 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();
 - }
 - }
 
在loop中首先獲取了當(dāng)前所在線程的Looper,同時(shí)也獲取到了Looper中的MessageQueue,說(shuō)明Looper已經(jīng)與當(dāng)前的線程進(jìn)行了綁定。在后面開(kāi)啟了一個(gè)for的死循環(huán),發(fā)現(xiàn)它做的事件是不斷的從消息隊(duì)列中取出消息,***都交給msg.target調(diào)用它的dispatchMessage方法,那么target又是什么呢?我們進(jìn)入Message
Message
- /*package*/ int flags;
 - /*package*/ long when;
 - /*package*/ Bundle data;
 - /*package*/ Handler target;
 - /*package*/ Runnable callback;
 - // sometimes we store linked lists of these things
 - /*package*/ Message next;
 
發(fā)現(xiàn)它就是我們熟悉的Handler,說(shuō)明***調(diào)用的就是Handler中的dispatchMessage方法,對(duì)消息的分發(fā)處理。這樣一來(lái)Handler就通過(guò)Looper聯(lián)系上了Looper所綁定的線程,即為主線程。
Handler
- 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;
 - }
 
通過(guò)Handler的初始化,它獲取了它所處線程的Looper,同時(shí)也獲取了Looper中的消息隊(duì)列。當(dāng)然如果所處線程的Looper為空的話就會(huì)拋出異常,這就解釋了為什么在非主線程中創(chuàng)建Handler要分別調(diào)用Looper.prepare與Looper.loop而主線程則不需要,因?yàn)樗J(rèn)已經(jīng)調(diào)用了。
dispatchMessage
- public void dispatchMessage(Message msg) {
 - if (msg.callback != null) {
 - handleCallback(msg);
 - } else {
 - if (mCallback != null) {
 - if (mCallback.handleMessage(msg)) {
 - return;
 - }
 - }
 - handleMessage(msg);
 - }
 - }
 - private static void handleCallback(Message message) {
 - message.callback.run();
 - }
 
回到前面,對(duì)于dispatchMessage的處理,首先判斷msg.callback是否為空,這里callback通過(guò)上面的Message應(yīng)該能知道他就是一個(gè)Runnable,如果不為空則直接調(diào)用Runnable的run方法。否則調(diào)用Handler的handleMessage方法.而這個(gè)方法相信大家已經(jīng)很熟悉了,對(duì)事件的處理都是在這個(gè)方法中執(zhí)行的。因?yàn)橥ㄟ^(guò)前面我們已經(jīng)知道了Handler已經(jīng)聯(lián)系上了主線程,所以handleMessage中的處理自然相對(duì)于在主線程中進(jìn)行,自然也能更新UI了。通過(guò)這里我們能把Looper比作是一個(gè)橋梁,來(lái)連接Looper所在的線程與Handler之間的通信,同時(shí)管理消息隊(duì)列MessageQueue中的消息。那么前面的Runnable又是如何不為空的呢?我們使用Handler有兩種方法,一種是直接創(chuàng)建一個(gè)Handler并且重寫(xiě)它的handleMessage方法,而另一種可以通過(guò)Handler.post(Runnable)來(lái)使用,這樣事件的處理自然就在run方法中實(shí)現(xiàn)。
上面介紹了Handler是如何聯(lián)系上了需要操作的線程與對(duì)消息是如何取出與處理的。下面來(lái)談?wù)勏⑹侨绾畏湃氲絃ooper中的MessageQueue中的。
sendMessageAtTime
通過(guò)Handler發(fā)送消息的方式很多,例如:sendMessage、sendEmptyMessage與sendMessageDelayed等,其實(shí)到***他們調(diào)用的都是sendMessageAtTime方法。所以還是來(lái)看下sendMessageAtTime方法中的實(shí)現(xiàn)。
- 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);
 - }
 
而sendMessageAtTime則就是調(diào)用了enqueueMessage操作,看這方法名就知道是入隊(duì)列操作了。
enqueueMessage
- private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
 - msg.target = this;
 - if (mAsynchronous) {
 - msg.setAsynchronous(true);
 - }
 - return queue.enqueueMessage(msg, uptimeMillis);
 - }
 
果不其然直接調(diào)用了MessageQueue中的queue.enqueueMessage(msg, uptimeMillis)將消息加入消息隊(duì)列,同時(shí)這段代碼msg.target = this 將當(dāng)前的Handler賦給了msg.target,這就是前面所說(shuō)的Looper.loop方法中調(diào)用的Handler。這樣就把消息放到了MessageQueue中,進(jìn)而通過(guò)前面所講的loop來(lái)取出消息進(jìn)行相應(yīng)的處理,這樣就構(gòu)成了整個(gè)對(duì)消息進(jìn)行處理的系統(tǒng)。這也是使用Handler內(nèi)部所發(fā)生的原理。好了Handler、Looper與MessageQueue它們之間的聯(lián)系基本就是這些了。我也簡(jiǎn)單畫(huà)了張圖希望有所幫助
總結(jié)
來(lái)總結(jié)下它們之間的流程。首先創(chuàng)建Handler而在Handler所處的線程中必須要有一個(gè)Looper,如果在主線程中默認(rèn)幫我們實(shí)現(xiàn)了,其他線程必須調(diào)用Looper.prepare來(lái)創(chuàng)建Looper同時(shí)調(diào)用Looper.loop開(kāi)啟對(duì)消息的處理。每個(gè)Looper中都有一個(gè)MessageQueue它是用來(lái)存儲(chǔ)Message的,Handler通過(guò)post或者send..等一系列操作通過(guò)Looper將消息放入到消息隊(duì)列中,而Looper通過(guò)開(kāi)啟一個(gè)***的循環(huán)來(lái)一直監(jiān)聽(tīng)著消息的處理,不斷從MessageQueue中取出消息,并交給與當(dāng)前Looper所綁定的handler的dispatchMessage進(jìn)行分發(fā),***根據(jù)情況調(diào)用Runnable的run或者Handler的HandlerMessage方法對(duì)消息進(jìn)行***的處理。
















 
 
 

 
 
 
 