public static final Looper myLooper() { return (Looper)sThreadLocal.get(); }
先來個Handler執(zhí)行過程的總結:
1、 Looper.prepare()方法
為當前線程綁定looper,
在looper構造方法中創(chuàng)建一個messageQueue
2、 創(chuàng)建handler 重并寫handleMessage方法
3、 使用handler發(fā)送消息,最終消息都會發(fā)送至messageQueue對象中,在messageQueue當中,所有的message按應該執(zhí)行的時間的先后順序,從小到大排列
4、Looper.loop()
在此方法中,開啟死循環(huán),不斷的從messageQueue中取出應該執(zhí)行的message,并執(zhí)行message 對應的handler中的dispatchMessage方法,即,執(zhí)行我們重寫的handleMessage方法
參照以上分析在子線程中創(chuàng)建Handler對象:
new Thread(){ @Override public void run() { Message msg = Message.obtain(); Looper.prepare();//若沒有調用此方法則拋出異常 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)建前調用Looper.prepare()方法在創(chuàng)建后調用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"); } // 為當前線程綁定一個looper對象,以sThreadLocal為key sThreadLocal.set(new Looper()); }即:調用Looper.prepare方法時為當前線程綁定了一個Looper對象,所以Looper.prepare方法只能調用一次,即一個線程只能有一個Looper對象
再看看Looper的構造方法:
private Looper() { mQueue = new MessageQueue(); }因為一個線程只能有一個Looper對象,所以一個線程也只能有一個MessageQueue對象
先讓我們看看Handler的構造方法:
public Handler() { //獲得當前線程的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方法:即獲取調用Looper.prepare方法時保存在sThreadLoad的Looper對象,所以Looper.prepare方法要在new Handler方法前調用
public static final Looper myLooper() { return (Looper)sThreadLocal.get(); }
即:當創(chuàng)建Handler時會先調用Looper.myLooper()方法獲取當前線程的Looper對象,如果Looper==null,則拋出異常
通過以上兩個方法,當前線程的唯一Looper對象和MessageQueue對象都已創(chuàng)建,接下來該sendMessage了
查看系統(tǒng)源碼可知:sendEmptyMessage等,發(fā)送信息的方法,最終都是調用了SendMessageAtTime(msg,when);
而SendMessageAtTime(msg,when);方法最終的目的就是為了queue.enqueueMessage(msg, uptimeMillis);,其中msg為發(fā)送的Message對象,uptimeMillis為SystemClock.uptimeMillis() + when
查看系統(tǒng)的enqueueMessage方法,該方法最終實現(xiàn)在messageQueue當中,所有的message按執(zhí)行的先后順序,從小到大排列
final boolean enqueueMessage(Message msg, long when) { msg.when = when; // 將執(zhí)行時間設置給msg.when Message p = mMessages; // 定義變量p = mMessage ,mMessage初終指向對列的第一個Message 對象 if (p == null || when == 0 || when< p.when) { // 當隊列中為空的時候,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ā)送成功這時候該調用Looper.loop方法:即完成了從MessageQueue中取出需要執(zhí)行的Message,并執(zhí)行我們重寫的handlMessage方法
public static final void loop() { //獲得當前線程的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 對應的handler中的dispatchMessage方法,即,執(zhí)行我們重寫的handleMessage方法 msg.target.dispatchMessage(msg); } } }