Handler,Looper,MessageQueue原理分析

Handler機(jī)制在android開(kāi)發(fā)中經(jīng)常使用,一直沒(méi)搞明白Handler,Looper,MessageQueue它們之間的關(guān)系,此次就從源碼的角度分析一下

1. 簡(jiǎn)述

Looper負(fù)責(zé)創(chuàng)建MessageQueue,然后進(jìn)入無(wú)限循環(huán)體中不斷從MessageQueue取出消息,觸發(fā)消息的分發(fā)處理,而Handler負(fù)責(zé)發(fā)送消息

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存儲(chǔ)了Looper對(duì)象,而且此方法不能運(yùn)行兩次,否則拋出異常.

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 (;;) { //此處無(wú)限循環(huán),取出消息
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); //分發(fā)處理消息
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對(duì)象,如果looper為null則拋出異常,也說(shuō)明prepare()在loop()之前運(yùn)行
>public static Looper myLooper() {
return sThreadLocal.get();
}

下一步是拿到MessageQueue,即me.Queue;
再進(jìn)入開(kāi)頭所說(shuō)的無(wú)限循環(huán),取出消息msg;
最后就是msg.target.dispatchMessage(msg),分發(fā)處理,target就是Handler.

概括Looper作用:

  1. 與當(dāng)前線程綁定,保證一個(gè)線程只會(huì)有一個(gè)Looper實(shí)例,同時(shí)一個(gè)Looper實(shí)例也只有一個(gè)MessageQueue。
  2. loop()方法,不斷從MessageQueue中去取消息,交給消息的target屬性的dispatchMessage去處理。
    下面就該Handler發(fā)送消息了
  • Handler
  1. Handler與MessageQueue綁定
    看Handler構(gòu)造方法

    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;  
    }  
    

通過(guò)Looper.myLooper()獲取了當(dāng)前線程保存的Looper實(shí)例,然后又獲取了這個(gè)Looper實(shí)例中保存的MessageQueue(消息隊(duì)列),這樣就保證了handler的實(shí)例與我們Looper實(shí)例中MessageQueue關(guān)聯(lián)上了

下面看發(fā)送消息的方法

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);  
}       

此處調(diào)用了下面這個(gè)方法:

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,也就是把當(dāng)前的handler作為msg的target屬性。最終會(huì)調(diào)用queue的enqueueMessage的方法,也就是說(shuō)handler發(fā)出的消息,最終會(huì)保存到消息隊(duì)列中去。

現(xiàn)在已經(jīng)很清楚了Looper會(huì)調(diào)用prepare()和loop()方法,在當(dāng)前執(zhí)行的線程中保存一個(gè)Looper實(shí)例,這個(gè)實(shí)例會(huì)保存一個(gè)MessageQueue對(duì)象,然后當(dāng)前線程進(jìn)入一個(gè)無(wú)限循環(huán)中去,不斷從MessageQueue中讀取Handler發(fā)來(lái)的消息。然后再回調(diào)創(chuàng)建這個(gè)消息的handler中的dispathMessage方法,下面我們趕快去看一看這個(gè)方法:

public void dispatchMessage(Message msg) {  
    if (msg.callback != null) {  
        handleCallback(msg);  
    } else {  
        if (mCallback != null) {  
            if (mCallback.handleMessage(msg)) {  
                return;  
            }  
        }  
        handleMessage(msg);  
    }  
}  

可以看到調(diào)用了 handleMessage(msg)方法;

 public void handleMessage(Message msg) {  
}  

這是一個(gè)空方法,因?yàn)橄⒌淖罱K回調(diào)都是我們自己實(shí)現(xiàn)的,在handler中實(shí)現(xiàn)handleMessage();

好了,現(xiàn)在總結(jié)一下整個(gè)流程:
1、首先Looper.prepare()在本線程中保存一個(gè)Looper實(shí)例,然后該實(shí)例中保存一個(gè)MessageQueue對(duì)象;因?yàn)長(zhǎng)ooper.prepare()在一個(gè)線程中只能調(diào)用一次,所以MessageQueue在一個(gè)線程中只會(huì)存在一個(gè)。
2、Looper.loop()會(huì)讓當(dāng)前線程進(jìn)入一個(gè)無(wú)限循環(huán),不端從MessageQueue的實(shí)例中讀取消息,然后回調(diào)msg.target.dispatchMessage(msg)方法。
3、Handler的構(gòu)造方法,會(huì)首先得到當(dāng)前線程中保存的Looper實(shí)例,進(jìn)而與Looper實(shí)例中的MessageQueue想關(guān)聯(lián)。
4、Handler的sendMessage方法,會(huì)給msg的target賦值為handler自身,然后加入MessageQueue中。
5、在構(gòu)造Handler實(shí)例時(shí),我們會(huì)重寫(xiě)handleMessage方法,也就是msg.target.dispatchMessage(msg)最終調(diào)用的方法。

  • Handler post
    一般使用方法
    mHandler.post(new Runnable()
    {
    @Override
    public void run()
    {
    Log.e("TAG", Thread.currentThread().getName());
    }
    });
    看輸出結(jié)果,當(dāng)前thread就是handler所在線程,并不會(huì)單獨(dú)創(chuàng)建線程,看源碼:

     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設(shè)置為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);  
   }  
 }  

此時(shí)因msg.callback != null,所以直接執(zhí)行handleCallback(msg);

private static void handleCallback(Message message) {        
    message.callback.run();
  }  

handleCallback()其實(shí)就只執(zhí)行的Runnable的run方法,所以handler.post不會(huì)另開(kāi)線程;
嗯,到此就全部結(jié)束了,相信對(duì)Handler,Looper,MessageQueue之間的關(guān)系都有了解了吧.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容