引言
????Android消息機(jī)制肯定是最被經(jīng)常提起的一個(gè)概念,通過(guò)下面的文章希望大家可以理解Message、?Handler、Looper。
1 消息處理流程
? ?在子線(xiàn)程中更新UI,先使用Handler的sendMessage去發(fā)送Message對(duì)象,然后通過(guò)Handler的handleMessage()方法中獲得剛才發(fā)送的Message對(duì)象,這就是一個(gè)消息處理流程,是常用的一種情況。
new Thread(new Runnable() {
????@Override
????public void run() {
? ? ? ? ? ? Message message = Message.obtain();
? ? ? ????? mHandler.sendMessage(message);
? ????? }
}).start();
mHandler =new Handler(new Handler.Callback() {
????@Override
? ? public boolean handleMessage(Message msg) {
????????return false;
? ? }
});
2 Message
? ? Google官方建議實(shí)例化Message時(shí)使用obtain方法,而不是直接new Message。因?yàn)镸essage維護(hù)著一個(gè)對(duì)象池,使用obtain方法能夠復(fù)用之前被回收的Message,下面代碼 if 語(yǔ)句就是復(fù)用Message。
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();
}
? ? 而Message的回收是調(diào)用了方法recycleUnchecked,可以看出來(lái)對(duì)象池有最大數(shù)量(MAX_POOL_SIZE)它的值是50,并且對(duì)象池是一個(gè)單鏈表,單鏈表的優(yōu)勢(shì)就是方便插入、刪除和節(jié)約內(nèi)存。
private static final int MAX_POOL_SIZE = 50;
void recycleUnchecked() {
? ? 省略掉部分初始化代碼……
? ? synchronized (sPoolSync) {
????????if (sPoolSize < ?MAX_POOL_SIZE) {
????????????next =sPool;
? ? ? ? ? ? sPool =this;
? ? ? ? ? ? sPoolSize++;
? ? ? ????? }
????}
}
3?Handler
? ? 為了防止內(nèi)存泄漏,將Handler聲明為靜態(tài)類(lèi)。一般情況下,通過(guò)Handler的sendMessage方法發(fā)送Message,最后調(diào)用msg.dispatchMessage(msg)回調(diào)到handleMessage方法。
static class MyHandler extends Handler {
? ? ? ? WeakReference mWeakReference;
? ? ? ? public MyHandler(Activity activity){
? ? ? ? ? ? mWeakReference=new WeakReference(activity);
?????????}
? ? ? ? @Override
? ? ? ? public void handleMessage(Message msg) {
? ? ? ? ? ? final Activity activity=mWeakReference.get();
? ? ? ? ? ? if(activity!=null) {
? ? ? ? ? ? ? ? ? ? //
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
3.1 Handler構(gòu)造方法
? ?Handler有七個(gè)構(gòu)造方法,不難看出①②③最后都會(huì)調(diào)用④。然后通過(guò)?Looper.myLooper()獲取到Looper對(duì)象,再通過(guò)mLooper.mQueue獲取到MessageQueue對(duì)象,最后我們會(huì)調(diào)用sendMessage方法發(fā)送Message對(duì)象到MessageQueue中。
? ① ?public Handler() { this(null, false);}
? ② ?public Handler(Callback callback) {this(callback, false);}
? ③ ?public Handler(boolean async) { this(null, async); }
? ④ ?public Handler(Callback callback, boolean async) {
????????if (FIND_POTENTIAL_LEAKS) {
????????????final Class 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;
}
? ? 查看myLooper的源碼不難看出,myLooper是從sThreadLocal中獲取到該線(xiàn)程下的Looper。
public static @Nullable Looper myLooper() {
????return sThreadLocal.get();
}
? ? 構(gòu)造方法⑤⑥最終會(huì)調(diào)用⑦,它們和前面四種構(gòu)造方法不同之處在于可以指定Looper。
⑤ ?public Handler(Looper looper) { this(looper, null, false); }
⑥ ?public Handler(Looper looper, Callback callback) { this(looper, callback, false); }
⑦ ?public Handler(Looper looper, Callback callback, boolean async) {
????????mLooper = looper;
????????mQueue = looper.mQueue;
????????mCallback = callback;
????????mAsynchronous = async;
}
3.2?sendMessage方法
????創(chuàng)建完Handler對(duì)象之后,通過(guò)sendMessage發(fā)送對(duì)象,不難看出最后調(diào)用了sendMessageAtTime方法,通過(guò)MessageQueue queue = mQueue取得構(gòu)造Handler時(shí)所獲得的MessageQueue對(duì)象。
??? 源碼中還有幾個(gè)發(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);
}
? ? 通過(guò)enqueueMessage方法將Message加入MessageQueue 中,閱讀源碼發(fā)現(xiàn)Handler方法發(fā)送的Message最后都要到MessageQueue中。
? ? msg.target其實(shí)就是Handler自己,它的作用是用來(lái)調(diào)用自己的dispatchMessage方法,在Looper的loop方法中會(huì)說(shuō)到。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
????msg.target =this;
? ? if (mAsynchronous) {
????????msg.setAsynchronous(true);
? ? }
????return queue.enqueueMessage(msg, uptimeMillis);
}
3.3?dispatchMessage
????調(diào)用dispatchMessage方法時(shí)會(huì)判斷msg是否有callback,而這個(gè)callback就是Runnable,通過(guò)對(duì)post的講解你就會(huì)明白是怎么回事。
public void dispatchMessage(Message msg) {
????if (msg.callback !=null) {
????????handleCallback(msg);
? ? ?}else {
????????if (mCallback !=null) {
????????????if (mCallback.handleMessage(msg)) {
????????????????return;
? ? ? ? ? ? ?}
????????}
????????handleMessage(msg);
? ? }
}
? ? 我們經(jīng)常會(huì)用到post,這個(gè)post并非真的創(chuàng)建新線(xiàn)程,?而是將Runnable封裝到Message中。
mHandler.post(new Runnable() {
????@Override
? ? public void run() {
????}
});
public final boolean post(Runnable r, long delayMillis)
{
????return sendMessageDelayed(getPostMessage(r), delayMillis);
}
private static Message ?getPostMessage(Runnable r) {
????Message m = Message.obtain();
? ? m.callback = r;
? ? return m;
}
? ? 閱讀dispatchMessage源碼發(fā)現(xiàn),如果callback不為null就調(diào)用handleCallback,callback為null則調(diào)用handleMessage??梢钥丛诔鰜?lái)post中的Runnable最后會(huì)在handleCallback中執(zhí)行它的run方法,并沒(méi)有創(chuàng)建新的線(xiàn)程去執(zhí)行run。
private static void handleCallback(Message message)?
????message.callback.run();
}
4 Looper
? ? 有了Message和Handler,但是還有在一個(gè)問(wèn)題,3.1中說(shuō)到的從sThreadLocal中獲取Looper,這個(gè)Looper是誰(shuí)保存到sThreadLocal中的?其實(shí)就是Looper創(chuàng)建時(shí)保存的。
? ? 在Looper這個(gè)類(lèi)中有兩個(gè)重要的方法,分別是prepare和loop方法。prepare負(fù)責(zé)創(chuàng)建Looper,loop負(fù)責(zé)無(wú)限循環(huán)讀取消息。
4.1?prepare
? ? Looper的prepare方法可以去實(shí)例化一個(gè)Looper,通過(guò)sThreadLocal.set(new Looper(quitAllowed))這行代碼可以看出來(lái),prepare創(chuàng)建了一個(gè)Looper加入到sThreadLocal中。
public static void prepare() {
????prepare(true);
}
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));
}
? ? 在實(shí)例化Looper時(shí)就會(huì)創(chuàng)建MessageQueue,所以MessageQueue并不需要我們手動(dòng)創(chuàng)建。通過(guò)上面的 if 語(yǔ)句可以看出,一個(gè)線(xiàn)程里只能有一個(gè)Looper,否則會(huì)拋出"Only one Looper may be created per thread",因此MessageQueue在一個(gè)線(xiàn)程中也只能有一個(gè)。
? ? 通過(guò)下面的代碼我們也可以得出另一個(gè)結(jié)論,在子線(xiàn)程中必須先調(diào)用looper.prepare才能使用handler,否則handler會(huì)無(wú)法發(fā)送消息,因?yàn)闆](méi)有MessageQueue。
private Looper(boolean quitAllowed) {
????mQueue =new MessageQueue(quitAllowed);
? ? mThread = Thread.currentThread();
}
4.2 loop
????一般在子線(xiàn)程中是這么使用loop的。先使用Looper.prepare()創(chuàng)建Looper,然后發(fā)送消息,最后再使用Looper.loop()無(wú)限循環(huán)讀取消息回調(diào)到handleMessage。
Looper.prepare();
Message message = Message.obtain();
mHandler.sendMessage(message);
Looper.loop();
????loop的源碼比較長(zhǎng),只分析關(guān)鍵點(diǎn),完整源碼請(qǐng)自行查看。 ? ?
? ? 首先通過(guò)myLooper獲取到Looper對(duì)象。
????從下面的代碼可以看出Looper不能為null不然會(huì)拋出"No Looper; Looper.prepare() wasn't called on this thread.",所以loop方法必須在Looper.prepare方法后使用。
final Looper me =myLooper();
? ? if (me ==null) {
????????throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
????}
public static @Nullable Looper?myLooper() {
????return sThreadLocal.get();
}
? ? ?loop方法是通過(guò)me.mQueue取得MessageQueue的。
final MessageQueue queue = me.mQueue;
? ? 那么,loop是怎么實(shí)現(xiàn)無(wú)線(xiàn)循環(huán)的呢?關(guān)鍵就在于它的for循環(huán)。
? ? 然后通過(guò)queue.next()去MessageQueue中獲取消息,接著使用msg.target.dispatchMessage(msg)去分發(fā)消息(msg.target就是前面在講Handler時(shí)說(shuō)到的Handler本身),至此一個(gè)消息處理流程就分析完了。
for (;;) {
????Message msg = queue.next(); // might block
? ? if (msg ==null) {
????????// No message indicates that the message queue is quitting.
? ? ? ? return;
? ? ?}
????try {
????????msg.target.dispatchMessage(msg);
????} ? ??
}
五 整體流程總結(jié)

? ? 首先由Looper.prepare創(chuàng)建Looper,Looper會(huì)創(chuàng)建MessageQueue,因?yàn)橐粋€(gè)線(xiàn)程只有一個(gè)Looper,所以一個(gè)線(xiàn)程只有一個(gè)MessageQueue。
? ? 接著創(chuàng)建Message,創(chuàng)建Message對(duì)象使用obtain方法,而不是直接new出來(lái),因?yàn)镸essage內(nèi)部維護(hù)這一個(gè)對(duì)象池,可以復(fù)用之前已經(jīng)使用過(guò)的Message對(duì)象,如果線(xiàn)程池為null會(huì)創(chuàng)建一個(gè)新的Message(new Message)。
? ? 再接著創(chuàng)建一個(gè)Handler,調(diào)用sendMessage發(fā)送Message到MessageQueue(MessageQueue并非真正的隊(duì)列,而是一個(gè)單鏈表)。
? ? 最后調(diào)用Looper.loop循環(huán)讀取消息,并調(diào)用Handler的dispatchMessage進(jìn)行回調(diào)處理?;卣{(diào)完之后調(diào)用msg.recycleUnchecked方法將msg加入到Message維護(hù)的對(duì)象池中。