public static final Looper myLooper() { return (Looper)sThreadLocal.get(); }
先來個Handler執(zhí)行過程的總結(jié):
1、 Looper.prepare()方法
為當(dāng)前線程綁定looper,
在looper構(gòu)造方法中創(chuàng)建一個messageQueue
2、 創(chuàng)建handler 重并寫handleMessage方法
3、 使用handler發(fā)送消息,最終消息都會發(fā)送至messageQueue對象中,在messageQueue當(dāng)中,所有的message按應(yīng)該執(zhí)行的時間的先后順序,從小到大排列
4、Looper.loop()
在此方法中,開啟死循環(huán),不斷的從messageQueue中取出應(yīng)該執(zhí)行的message,并執(zhí)行message 對應(yīng)的handler中的dispatchMessage方法,即,執(zhí)行我們重寫的handleMessage方法
參照以上分析在子線程中創(chuàng)建Handler對象:
new Thread(){ @Override public void run() { Message msg = Message.obtain(); Looper.prepare();//若沒有調(diào)用此方法則拋出異常 Can't create handler inside thread that has not called Looper.prepare() Handler handler2 = new Handler(){ public void handleMessage(Message msg) { Toast.makeText(MainActivity.this, "收到子線程message消息", 0).show(); }; }; handler2.sendMessage(msg); Looper.loop(); } }.start();對比在主線程中創(chuàng)建Handler實例對象我們發(fā)現(xiàn),在子線程中創(chuàng)建Handler對象需要在創(chuàng)建前調(diào)用Looper.prepare()方法在創(chuàng)建后調(diào)用Looper.loop方法,那究竟這兩個方法是做什么的呢?
先看看系統(tǒng)的Looper.prepare方法:
public static final void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } // 為當(dāng)前線程綁定一個looper對象,以sThreadLocal為key sThreadLocal.set(new Looper()); }即:調(diào)用Looper.prepare方法時為當(dāng)前線程綁定了一個Looper對象,所以Looper.prepare方法只能調(diào)用一次,即一個線程只能有一個Looper對象
再看看Looper的構(gòu)造方法:
private Looper() { mQueue = new MessageQueue(); }因為一個線程只能有一個Looper對象,所以一個線程也只能有一個MessageQueue對象
先讓我們看看Handler的構(gòu)造方法:
public Handler() { //獲得當(dāng)前線程的looper對象 mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } // 獲得looper中MessageQueue的引用 mQueue = mLooper.mQueue; }
再看看系統(tǒng)的Looper.myLooper方法:即獲取調(diào)用Looper.prepare方法時保存在sThreadLoad的Looper對象,所以Looper.prepare方法要在new Handler方法前調(diào)用
public static final Looper myLooper() { return (Looper)sThreadLocal.get(); }
即:當(dāng)創(chuàng)建Handler時會先調(diào)用Looper.myLooper()方法獲取當(dāng)前線程的Looper對象,如果Looper==null,則拋出異常
通過以上兩個方法,當(dāng)前線程的唯一Looper對象和MessageQueue對象都已創(chuàng)建,接下來該sendMessage了
查看系統(tǒng)源碼可知:sendEmptyMessage等,發(fā)送信息的方法,最終都是調(diào)用了SendMessageAtTime(msg,when);
而SendMessageAtTime(msg,when);方法最終的目的就是為了queue.enqueueMessage(msg, uptimeMillis);,其中msg為發(fā)送的Message對象,uptimeMillis為SystemClock.uptimeMillis() + when
查看系統(tǒng)的enqueueMessage方法,該方法最終實現(xiàn)在messageQueue當(dāng)中,所有的message按執(zhí)行的先后順序,從小到大排列
final boolean enqueueMessage(Message msg, long when) { msg.when = when; // 將執(zhí)行時間設(shè)置給msg.when Message p = mMessages; // 定義變量p = mMessage ,mMessage初終指向?qū)α械牡谝粋Message 對象 if (p == null || when == 0 || when< p.when) { // 當(dāng)隊列中為空的時候,mMessage = msg msg.next = p; mMessages = msg; this.notify(); } else { // 否則將要進入隊列的msg的執(zhí)行時間和隊列中的message的執(zhí)行時間進行比較, // 最終會使messageQueue中的所有的message按時間為順序從小到大排列 // 即按執(zhí)行的先后順序排列 Message prev = null; while (p != null && p.when<= when) { prev = p; p = p.next; } msg.next = prev.next; prev.next = msg; this.notify(); } }
消息發(fā)送成功這時候該調(diào)用Looper.loop方法:即完成了從MessageQueue中取出需要執(zhí)行的Message,并執(zhí)行我們重寫的handlMessage方法
public static final void loop() { //獲得當(dāng)前線程的looper對象及messageQueue對象 Looper me = myLooper(); MessageQueue queue = me.mQueue; //開啟while(true)循環(huán) while (true) { //從消息隊列中取出一個message,如果message執(zhí)行時間不到,那就wait等一會 Message msg = queue.next(); // might block //執(zhí)行message 對應(yīng)的handler中的dispatchMessage方法,即,執(zhí)行我們重寫的handleMessage方法 msg.target.dispatchMessage(msg); } } }