Android的消息机制: Message/MessageQueue/Handler/Looper
Message * 最好通過Message.obtain()來創(chuàng)建Message對象,從消息池里創(chuàng)建Message更高效。 源碼分析 public final class Message implements Parcelable { public int what; // 用戶定義的標(biāo)識碼 public int arg1; // 用來存儲簡單的數(shù)據(jù),這樣可以不使用Object/Bundle來做消息。 public int arg2; public Object obj; // 對象型數(shù)據(jù)。 public Messenger replyTo;? Bundle data; // 復(fù)雜型消息數(shù)據(jù) // Message的最終處理分兩種情況: Handler target; // 1)通過Message的target(Handler)處理消息,具體是Handelr實現(xiàn)handleMessage()。 Runnable callback; // 2)通過空消息的callback(Runnable)處理消息,具體是丟棄Message,然后直接調(diào)用run()。 private static final Object sPoolSync = new Object(); // 消息池用到的鎖 private static Message sPool ; // 從消息池中取出的可用的消息對象。每取一次,這里就放置一個可用的。 private static int sPoolSize = 0; // 當(dāng)前可用的消息對象數(shù)量 private static final int MAX_POOL_SIZE = 50 ; ?// 池存放最大量 Message next; // 實現(xiàn)鏈表式消息池 // 從消息池中取一個可用的消息對象 public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null;? sPoolSize--; return m; } } return new Message(); } // 從現(xiàn)有Message復(fù)制并返回 public static Message obtain(Message orig) { Message m = obtain(); m.what = orig.what; m.arg1 = orig.arg1; m.arg2 = orig.arg2; m.obj = orig.obj; m.replyTo = orig.replyTo; if (orig.data != null) { m.data = new Bundle(orig.data); } m.target = orig.target; m.callback = orig.callback; return m; } // 發(fā)送消息? public void sendToTarget() { target.sendMessage(this); //?調(diào)用的是 handler 的 sendMessage() } // 消息回收 public void recycle() { clearForRecycle(); // 清除Message對象的所有信息 synchronized (sPoolSync) { if(sPoolSize < MAX_POOL_SIZE){ next = sPool; // 下一個可用Message是當(dāng)前sPool(可用) sPool = this ; // 當(dāng)前可用的Message為正在釋放清除的Message對象 sPoolSize++; // 可用對象數(shù)量遞增 } } } } MessageQueue *?holding the list of messages to be dispatched by a?Looper。 * 不能直接向Looper的MessageQueue添加Message,需要通過Handler。 * 可通過 Looper.myQueue()獲取到當(dāng)前線程的MessageQueue。
Handler * 創(chuàng)建一個Handler就會綁定到當(dāng)前Thread/MessageQueue,之后,Handler可以向MessageQueue發(fā)送Message和Runnable,等候輪詢執(zhí)行。 * 發(fā)送一個Message:sendMessage(Message m)。 * 發(fā)送一個Runnable:post(Runnable r) 。 public class Handler { // 自定義的Handler必須實現(xiàn)該方法,用于處理消息 public void?handleMessage(Message msg){} // 或者指定一個實現(xiàn)了Callback接口的類 public interface Callback { public boolean?handleMessage(Message msg); } // 構(gòu)造函數(shù) // 默認(rèn)情況下,handler會關(guān)聯(lián)到當(dāng)前Thread的Looper,如果沒有Looper,拋異常 public Handler(Looper looper,Callback callback/*相當(dāng)于指定了handleMessage()函數(shù)*/,boolean async){? mLooper=looper; mQueue=looper.mQueue; mCallback =callback;mAsynchronous = async; } public final Message obtainMessage(){ return Message.obtain(this); } // 直接調(diào)用的Message的obtain // --------------------------------------------------------------- //?發(fā)送消息到MessageQueue // handler.sendXXX均調(diào)用此方法 public boolean sendMessageAtTime(Message msg,long uptimeMillis) { MessageQueue queue = mQueue; return enqueueMessage(queue,msg,uptimeMillis); } private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) {msg.setAsynchronous(true);} return queue.enqueueMessage(msg, uptimeMillis); } //?--------------------------------------------------------------- //?發(fā)送Runnable到MessageQueue // 原理是把Runnable附加到一個空消息的callback上,當(dāng)執(zhí)行消息時,如果發(fā)現(xiàn)有callback,則執(zhí)行callback。 public final boolean post(Runnable r) { return?sendMessageDelayed(getPostMessage(r),0); } private static getPostMessage(Runnable r,Object token) { Message m = Message.obtain(); m.obj = token; m.callback = r;?// 指定Message的callback為r。通過sendMessage的消息沒有callback,包含callback的Message將會被其callback執(zhí)行。 return m; } //?--------------------------------------------------------------- //?處理消息 // 消息在Looper中是通過調(diào)用這個函數(shù)來實現(xiàn)處理消息的 public void dispatchMessage(Message msg) { if(msg.callback!=null){?handleCallback(msg); } // 在Runnable中處理 else { handleMessage(msg); // 調(diào)用Handler處理消息的函數(shù) } } private static void?handleCallback(Message message) {? message.callback.run(); //消息被丟棄,并且直接調(diào)用run(),而不是新開線程。 } }// end handler()
Looper ? * 默認(rèn)線程并沒有包含可以循環(huán)處理消息的功能,Looper類可以幫助線程實現(xiàn)消息循環(huán)。 ? public final class Looper { static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); // 線程本地變量,每個線程一個Looper。 final Message mQueue; final Thread mThread; private Looper(boolean quitAllowed){ mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } // -------------------------------------------------------------------- // 準(zhǔn)備。為當(dāng)前線程創(chuàng)建一個Looper對象 static void prepare(boolean quitAllowed/*MessageQueue是否可退出*/) { if(sThreadLocal.get()!=null){/*Exception,當(dāng)前線程的Looper已存在,一個線程一個Looper*/} sThreadLocal.set(new Looper(quitAllowed)); } // -------------------------------------------------------------------- // 開始循環(huán) public static void loop() { final Looper me = myLooper();// 當(dāng)前線程的Looper實例 final MessageQueue queue = me.mQueue; for(;;){ Message msg = queue.next(); if(msg == null) {?return;} msg.target.dispatchMessage(msg); // 由Handler處理該消息 msg.recycle(); // 清理該消息,清空后返回消息池。 }//end for }// end loop() // -------------------------------------------------------------------- public void quit() { mQueue.quit(false); } public boolean isIdling(){ return mQueue.isIdling();} } // class end.
Demo
Demo#1 發(fā)送消息
class SomeActivity
{
@Override
public void onCreate(...){
testMessage();
}
void testMessage(){
MyHandler handler = new MyHandler();
// or
handler = new Handler(/*this.getMainLooper(),*/ new Handler.Callback(){ /*...*/ });
// 發(fā)送Message
Message m1 = new Message();
m.setTarget(h);
m.sendToTarget();
// 發(fā)送Runnable(內(nèi)部其實是發(fā)送了一個Message+Runnable)
handler.post(new Runnable(){
@Override
public void run(){
// 在主線程中運行
}
});
}
class MyHandler extends Handler{
@Override
public void handleMessage(Message msg){ /*...*/ }
}
Demo#2 自定義Looper線程
public static void testLooper()
{
Thread tLooper = new Thread(new Runnable(){
@Override
public void run() {
Looper.prepare();
MyHandler h = new MyHandler();
// 發(fā)送消息
h.sendEmptyMessage(0);
// 發(fā)送Runnable
h.post(new Runnable(){
@Override
public void run() {
Log.i("test","[in post runnable]threadid:"+Thread.currentThread().getId()); // tLooper線程ID
}});
Looper.loop(); // 一直循環(huán)。即使沒有消息
}});
tLooper.start();
}
references http://developer.android.com/reference/android/os/MessageQueue.html? http://developer.android.com/reference/android/os/Looper.html
總結(jié)
以上是生活随笔為你收集整理的Android的消息机制: Message/MessageQueue/Handler/Looper的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【心得】怪异的JS的Date函数
- 下一篇: git常见问题解决办法