本文只是表面的帶大家瀏覽下Handler,Looper,Message的源碼
android的訊息處理有三個核心類:Looper,Handler和Message。其實還有一個Message Queue(訊息佇列),
非同步處理大師 Handler:
什麼是handler?handler扮演了往MQ上添加訊息和處理訊息的角色(只處理由自己發出的訊息),即通知MQ它要執行一個任務(sendMessage),並在loop到自己的時候執行該任務(handleMessage),整個過程是非同步。handler建立時會關聯一個looper,預設的構造方法將關聯當前線程的looper,不過這也是可以set的。預設的構造方法:
public class handler { final MessageQueue mQueue; // 關聯的MQ final Looper mLooper; // 關聯的looper final Callback mCallback; // 其他屬性 public Handler() { 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()); } } // 預設將關聯當前線程的looper mLooper = Looper.myLooper(); // looper不可為空,即該預設的構造方法只能在looper線程中使用
//UI主線程中預設帶有一個Looper if (mLooper == null) { throw new RuntimeException(//不能在沒有Looper的線程上建立Handler, "Can't create handler inside thread that has not called Looper.prepare()"); } // 重要!!!直接把關聯looper的MQ作為自己的MQ,因此它的訊息將發送到關聯looper的MQ上 mQueue = mLooper.mQueue; mCallback = null; } // 其他方法 }
當然這隻是Handler的一個構造方法。Handler本身有四個建構函式,其他其他的三個你可以通過查看源碼來解析,大致雷同。
Handler發送訊息
有了handler之後,我們就可以使用 post(Runnabl),sendMessage(Message)
這些方法向MQ上發送訊息了。光看這些API你可能會覺得handler能發兩種訊息,一種是Runnable對象,一種是message對象,這是直觀的理解,但其實post發出的Runnable對象最後都被封裝成message對象了,見源碼:
Post發送的形式
public final boolean post(Runnable r){//使用Post發送訊息 return sendMessageDelayed(getPostMessage(r), 0);}
private final Message getPostMessage(Runnable r) {//把一個Runnable包轉成一個Message Message m = Message.obtain(); m.callback = r; return m;}
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){ boolean sent = false; MessageQueue queue = mQueue; if (queue != null) {
/*該handler對象,這確保了looper執行到該message時能找到處理它的handler,直白點就是ABC三個Handler發送訊息,最終執行的時候Message訊息
也是由他們本身來執行,而不會發生A接受到B發送的Message之類的情況*/ msg.target = this;//
sent = queue.enqueueMessage(msg, uptimeMillis);//壓入訊息佇列 }else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent;}
sendMessage(Message)形式
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); }
從源碼中我們中我們可以很清晰的看到無論是用psot(Runnable)還是使用sendMessage(Message)方法,最後他們都會調用到同一個方法壓入都一個隊列中去。
Handler處理訊息
那handler如何處理訊息。訊息的處理是通過核心方法是通過dispatchMessage(Message)來進行處理的,源碼如下:
public void dispatchMessage(Message msg) { if (msg.callback != null) {//post(Runnable)形式最終調用到這個方法 handleCallback(msg); } else {
/* 這種方法允許讓activity等來實現Handler.Callback介面或者構造Handler(Callback,避免了自己編寫handler重寫handleMessage方法*/ if (mCallback != null) {
if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg);//優先等級最低的就是 重寫HandlerMessage方法了 } }
封裝任務Message
Message的源碼中沒有特別的方法,對於Message我們應該記住下面的幾個知識點(等待大家補充)
1.儘管我們可以直接instance一個Message,但我們最好通過Message.obtain()來從訊息池中獲得空訊息對象,以節省資源。
2.如果你的message只需要攜帶簡單的int資訊,請優先使用Message.arg1和Message.arg2來傳遞資訊,這比用Bundle更省記憶體
3.擅用message.what欄位表示code,
即這個訊息具體是什麼類型的訊息.
每個what都在其handler的namespace中,
我們只需要確保將由同一個handler處理的訊息的what屬性不重複就可以.相當於判別類型
4.message.When 它大小由小到大排列, 排在最前面的訊息會首先得到處理,
因此可以說訊息佇列並不是一個嚴格的先進先出的隊列.
5.message.target 確定了最終你執行的時候由那個Handler來執行這個Message。一般來說誰壓入隊列就讓誰在抽取出來的時候去執行。通過上面的源碼我們可以查詢到
Looper管道哥
首先明確一點Activity本身在啟動的時候預設給了他一個Looper
Looper構造:
private Looper() { mQueue = new MessageQueue();//初始化Looper的時候的我們就給這個Looper配了一個MQ隊列,一一對應 mRun = true; mThread = Thread.currentThread();//綁定他所屬的線程 }
// 我們調用該方法會在調用線程的TLS中建立Looper對象 public static final void prepare() { if (sThreadLocal.get() != null) { // 試圖在有Looper的線程中再次建立Looper將拋出異常 throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); }
public static final void loop() { Looper me = myLooper();//從該線程中取出對應的looper對象 MessageQueue queue = me.mQueue;//取訊息佇列對象... while (true) { Message msg = queue.next(); // might block 這個方法還不是很懂。出去一個待處理的Message //if (!me.mRun) { // break; //} if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } if (me.mLogging!= null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); msg.target.dispatchMessage(msg); //訊息的抽取。最終的施行執行方法 if (me.mLogging!= null) me.mLogging.println( "<<<<< Finished to " + msg.target + " " + msg.callback); msg.recycle(); } } }
以上就是對Handler和Message還有Looper的源碼的表面認識