Handler , MessageQueue,Looper關係:java
Message 裏有一個Handler屬性api
Looper 裏有一個MessageQueue屬性安全
Handler 裏有一個MessageQueue(就是Looper裏的), Looperoop
建立的Handler的時候,會給Looper屬性賦值,這個是從當前線程中拿出來的。ui線程裏自帶一個,其餘線程裏只能手動的ui
Looper.prepare() 和 Looper.loop()this
Looper.prepare() 裏看當前線程有沒有綁定Looper,沒有的話建立一個spa
建立Looper時候,會給MessageQueue賦值。一個 Looper 對應一個MessageQueue線程
一個Handler把 Message 加到MessageQueue中,Looper負責從MessageQueue裏取Message,而後分發給Handlercode
----------------------------------------Handler發送消息到消息隊列-----------------------------------------------對象
Handler.sendMessage();內部仍是調用的sendMessageDelayed() ,只不過延時時間設爲0
調用順序是:sendMessage-->sendMessageDelayed()-->sendMessageAtTime()-->enqueueMessage()(僅僅給Message設一個target)-->queue.enqueueMessage()
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); }
能夠看到最後一行, enqueueMessage()
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
這個方法主要就是把Message的target設爲this,未來循環從MessageQueue取Message,能夠根據target,執行相應的handleMessage()。
看最後一行,Handler的enqueueMessage又調用了queue.enqueueMessage();
首先先看,enqueueMessage的方法簽名: boolean enqueueMessage(Message msg, long when) 。
參數 when,就是Message被分發給handler的時間
例如:當咱們調用的是handler.sendMessageDelayed(1000); 此時的when=SystemClock.uptimeMillis() + 1000
-------------------------------------Looper從MessageQueue取出Message------------------
再看handler.dispatchMessage()方法
/** * 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); } }
先看msg.callback 是否是爲空。這個callback究竟是什麼呢?
handler.send(Runnable runnable).
這個方法容許傳一個Runnable的對象進去,在裏面調用了下面的方法,把Runnable對象包裝成了Message。
private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }
這時Message.callback = r;
這時再看dispatchMessage裏若是callback不爲空, 則調用 handleCallback(msg);執行
private static void handleCallback(Message message) { message.callback.run(); }
-----------------------------------------Looper 退出------------------------------------------
Looper.quit()
public void quit() { mQueue.quit(false); }
當調用了這個方法後,再調用handler.sendMessage(Message)添加Message到MessageQueue ,就會返回false;
這個方法是不安全的,由於在Looper終止以前,可能還有一些Message沒有被交付完。所有被取消了
因此推薦使用Looprt.quitSafely(),注意這要api 18 以上纔可使用
public void quitSafely() { mQueue.quit(true); }
能夠看到這兩個方法都是調用mQueue.quit(); 只是傳進去的參數不同
void quit(boolean safe) { if (!mQuitAllowed) { throw new IllegalStateException("Main thread not allowed to quit."); } synchronized (this) { if (mQuitting) { return; } mQuitting = true; if (safe) { removeAllFutureMessagesLocked(); } else { removeAllMessagesLocked(); } // We can assume mPtr != 0 because mQuitting was previously false. nativeWake(mPtr); } }
其中,當正在退出時返回,不然將mQuitting標識爲true
而且根據傳進來的true或者false來決定時哪一種退出的策略
removeAllFutureMessagesLocked(); ///這種是先看隊首,若是執行時間沒到,那說明後續的都沒有到。則直接調用 removeAllMessagesLocked();不然,從隊首一個一個日後找,直接找到第一個時間沒到的Message m,從他開始一直到最後直接刪除。那麼m以前的是還能分發出去的。
removeAllMessagesLocked(); ///這種是直接刪除MessageQueue上全部的Message