寫在前面的話
簡書支持Markdown語法,從這篇文章開始称勋,后面的文章都會(huì)改成Markdown編輯胸哥,讓我們一起來學(xué)著使用Markdown吧。:)
在前面兩篇文章中
中我們介紹了Hanlder的構(gòu)造方法與Looper的初始化赡鲜。本篇中我們將對(duì)剩余部分進(jìn)行剩余部分的分析空厌。
主線程的Looper初始化
主線程的looper的初始化是在Looper.prepareMainLooper中進(jìn)行初始化的。而這個(gè)方法被調(diào)用位置在ActivityThread中main方法中其代碼引用如下:
Looper.prepareMainLopper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (false) { Looper.myLooper().setMessag } Looper.loop();
而ActivityThread的main方法是Android應(yīng)用程序主線程的入口蝗蛙,所以我們可以理解為:主線程的Looper在應(yīng)用啟動(dòng)時(shí)已經(jīng)初始化過了蝇庭。
Handler的消息發(fā)送
我們?cè)趧?chuàng)建好Handler后,使用Handler發(fā)送消息一般調(diào)用根據(jù)其方法調(diào)用有:
sendMessage()
sendEmptyMessage()
sendMessageAtTime()
sendMessageDelayed()
其中主要區(qū)別在于如下源碼展示:
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }
public final boolean sendEmptyMessage(int what) { return sendEmptyMessageDelayed(what, 0); }
public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, 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); }
可以看到捡硅,當(dāng)發(fā)送EmptyMessage時(shí)哮内,會(huì)在Handler中使用Message.obtain()來構(gòu)造一個(gè)Message,而如果發(fā)送無延時(shí)消息時(shí)壮韭,會(huì)設(shè)置延時(shí)時(shí)間為0北发,最后會(huì)發(fā)送都會(huì)調(diào)用sendMessageAtTime()方法。所有的消息都會(huì)通過enqueMessage發(fā)送出去喷屋。
注意:Hanlder中的enqueMessage中會(huì)調(diào)用其中messageQueue.enqueMessage(msg, uptimeMillis),但是Handler中的MessageQueue對(duì)象是從Looper中g(shù)et到的琳拨,所以,MessageQueue耦合的還是Looper
MessageQueue的消息遍歷
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; } if (needWake) { nativeWake(mPtr); }
如上圖中代碼中所示:其中主要操作是將新加入的Message與當(dāng)前的MessageQueue中的頭進(jìn)行比較屯曹,如果當(dāng)前有新消息進(jìn)入并且觸發(fā)時(shí)間為0或小于當(dāng)前頭節(jié)點(diǎn)的時(shí)間狱庇,如果隊(duì)列阻塞,則喚醒線程處理恶耽。如果新消息觸發(fā)時(shí)間長于隊(duì)列中的消息時(shí)間密任,則按時(shí)間排序,插入到隊(duì)列中偷俭。如果喚醒線程浪讳,則調(diào)用nativeWake函數(shù)進(jìn)行JNI方法調(diào)用發(fā)送消息。
消息循環(huán)處理與回調(diào)
Looper中的loop()方法會(huì)拿到與looper耦合的MessageQueue對(duì)象涌萤,由MessageQueue調(diào)用next()方法淹遵,如果meesage對(duì)象不為空口猜,則調(diào)用msg.target.dispatchMessage(msg);
回調(diào)到Handler中。
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
其中透揣,else語句中的handlerMessage最終會(huì)回調(diào)回當(dāng)時(shí)創(chuàng)建的Handler對(duì)應(yīng)的handMessage方法中济炎。
在回調(diào)中,我們注意到除了handleMessage的回調(diào)淌实,還有可以注冊(cè)message的CallBack或者Handler的callback來回調(diào)冻辩。message的Callback需要在message創(chuàng)建時(shí)傳入一個(gè)Runnable對(duì)象。而Handler的Callback與handleMessage方法就目前而言使用上沒感覺有什么區(qū)別拆祈。
希望有了解的同學(xué)能對(duì)這個(gè)問題留言說明下恨闪,謝謝~放坏!
寫到最后
Handler的基礎(chǔ)分析就算完成了,后續(xù)有時(shí)間會(huì)做其他相關(guān)的源碼分析钧敞。
不足之處麸粮,請(qǐng)大家批評(píng)指導(dǎo)弄诲。
ps:Markdown代碼框標(biāo)記不怎么好用,大家有什么建議也可以留言(⊙o⊙)哦寂玲!