本文用AndroidStudio追尋源碼的方式來分析Handler消息機制
1楔脯、應(yīng)用程序的入口是ActivityThread類中的main方法,當(dāng)打開應(yīng)用程序時,會首先調(diào)用ActivityThread類中的main()方法;而main()方法中主要調(diào)用了Looper.prepareMainLooper()和Looper.loop()兩個方法
public static final void main(String[] args) {
//初始化looper Looper.prepareMainLooper();
//將輪詢器輪詢起來
Looper.loop();
}
2、先看Looper類中的prepareMainLooper()方法泽论,調(diào)用了prepare(false)方法
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
//保證主線程Looper唯一
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
Looper中的prepare()方法,創(chuàng)建了Looper對象
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//創(chuàng)建Looper對象
sThreadLocal.set(new Looper(quitAllowed));
}
Looper的構(gòu)造方法卡乾,創(chuàng)建MessageQueue消息隊列
private Looper(boolean quitAllowed) {
//創(chuàng)建MessageQueue消息隊列
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
3翼悴、然后繼續(xù)調(diào)用ActivityThread類中的Looper.loop()方法
public static void loop() {
//獲取Looper對象和MessageQueue消息隊列
final Looper me = myLooper(); if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
//開始無限輪詢 ,注意這里是死循環(huán)在Android2.3的源碼時用的while(true)循環(huán)
for (;;) {
//只要消息隊列中有消息说订,不斷的從消息隊列中取消息
Message Message = queue.next();
might block if (Message == null) {
return;
}
//處理消息
Message.target.dispatchMessage(Message);
//回收消息
Message.recycleUnchecked();
}
}
4抄瓦、發(fā)送消息時創(chuàng)建Handler對象的過程潮瓶,Handler重載的構(gòu)造很多,但最終調(diào)用的是兩個钙姊,或者三個參數(shù)的構(gòu)造毯辅,最終目的就是將Looper對象和MessageQueue對象的引用保存到Handler的成員變量中
public Handler() {this(null, false);}
public Handler(Callback callback) {this(callback, false);}
public Handler(Looper looper) { this(looper, null, false);}
public Handler(Looper looper, Callback callback){this(looper,callback,false);}
public Handler(boolean async) {this(null, async);}
public Handler(Callback callback, boolean async) {
//獲取當(dāng)前線程的Looper對象,并保存到Handler的成員變量中
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");
}
//將Looper中的MessageQueue保存到Handler的成員變量中
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public Handler(Looper looper, Callback callback, boolean async) {
//獲取當(dāng)前線程的Looper對象煞额,并保存到Handler的成員變量中
mLooper = looper;
//將Looper中的MessageQueue保存到Handler的成員變量中
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
5思恐、然后我們要先明白,消息是從Message的回收隊列中取出來的膊毁,那我們?nèi)タ匆幌翸essage回收隊列的實現(xiàn)原理,回收消息是調(diào)用了Message類的recycle()方法
public void recycle() {
recycleUnchecked();
}
/*package*/ Message next;
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
void recycleUnchecked() {
synchronized (sPoolSync) {
//判斷回收隊列是否比隊列的最大值大
if (sPoolSize < MAX_POOL_SIZE) {
//此處代碼是消息回收隊列的核心代碼胀莹,我用圖來分析原理
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
6、接下來婚温,我們看一下如何從消息回收隊列取出一條消息描焰,一般我們用Message.obtain()方法來獲取一條空消息
public static Message obtain() {
synchronized (sPoolSync) {
//判斷消息池中是否有消息
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0;
// clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
7、現(xiàn)在空消息已經(jīng)獲取到栅螟,繼續(xù)看Handler發(fā)送消息的過程荆秦,我們發(fā)送消息有三種形式:最常見的是調(diào)用handler.sendMessage()發(fā)送一條消息,最終會調(diào)用handler.sendMessageAtTime(Message Message, long uptimeMillis)方法
public final boolean sendMessage(Message msg){ return sendMessageDelayed(msg, 0);}
public final boolean sendEmptyMessage(int what){ return sendEmptyMessageDelayed(what, 0);}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis);}
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) {
//獲取Handler中的消息隊列
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
//將要發(fā)送的消息和時間加入消息隊列
return enqueueMessage(queue, msg, uptimeMillis);
}
繼續(xù)看enqueueMessage(queue, msg, uptimeMillis)方法
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//將當(dāng)前handler對象的引用賦值給Message中的target變量
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//調(diào)用c庫中的方法將消息添加到消息隊列
return queue.enqueueMessage(msg, uptimeMillis);
}
8力图、第二種常見的發(fā)送消息的方法是handler.post(Runnable r),最終也是調(diào)用的sendMessageAtTime(Message msg, long uptimeMillis)方法,添加一條消息到消息隊列
public final boolean post(Runnable r){
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis){
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
接下來看Runnable 對象在哪被調(diào)用步绸,當(dāng)你用post的方式發(fā)送一條消息時,會調(diào)用getPostMessage()方法來獲取該消息吃媒,并將該消息的runnable的應(yīng)用賦值給Message的callback變量
/*package*/ Runnable callback;//Message類中的callback成員變量
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
//將runnable接口的引用賦值給Message的callback變量
m.callback = r;
return m;
}
9瓤介、第三種發(fā)送消息的方法是在創(chuàng)建Handler對象的時候傳一個Callback引用進去,Handler部分的代碼看第4條的代碼,Callback原來是個接口赘那,而且有一個抽象方法需要重寫刑桑,這和空參的new Handler(),原理是一樣的
public interface Callback {
public boolean handleMessage(Message msg);
}
10募舟、消息添加到消息隊列中后漾月,由Looper.loope();一直在執(zhí)行,會不斷從消息隊列中取出消息胃珍,并調(diào)用Message.target.dispatchMessage()方法處理消息
public void dispatchMessage(Message msg) {
//判斷Message中的callback變量是否為空
if (msg.callback != null) {
handleCallback(msg);
} else {
//判斷Handler中的mCallback變量是否為空
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//處理sendMessage();方法發(fā)送的消息
handleMessage(msg);
}
}
首先,Handler處理消息的時候會優(yōu)先判斷Message中的callback是否為null蜓陌,不為空的話調(diào)用handleCallback(Message)觅彰,執(zhí)行我們重寫的run()方法
private static void handleCallback(Message message) { message.callback.run();}
其次,Handler會判斷自己的成員變量mCallback是否為null钮热,不為空的話執(zhí)行mCallback.handleMessage(Message)填抬,也就是創(chuàng)建Handler對象時傳進去的接口的抽象方法
public interface Callback {
public boolean handleMessage(Message msg);
}
最后調(diào)用我們創(chuàng)建空參Handler對象時所重寫的handleMessage(Message msg)方法
//該方法為空實現(xiàn),是我們在創(chuàng)建Handler對象的時候重寫的handleMessage()方法隧期,根據(jù)msg.what進行消息處理
public void handleMessage(Message msg) {}
補充:
1飒责、Message回收隊列的實現(xiàn)原理
Message回收隊列赘娄,以鏈表的形式不斷的將回收到的Message添加到鏈表的頭部,此時消息的回收已經(jīng)完成了
2宏蛉、從Message回收隊列中獲取一條空消息進行復(fù)用
我還是以畫圖的形式來分析取消息的過程
3遣臼、發(fā)送一條消息到MessageQueue的過程分析,看MessageQueue中的enqueueMessage()方法中的代碼
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 {
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;
}
到現(xiàn)在,Handler消息的整體流程就走完了拾并,歡迎大家批評指正揍堰!
推薦:
Message在MessageQueue中的入列和出列流程
http://www.reibang.com/p/a8708d315039