1.Looper類
looper是線程的消息循環處理器,每個線程只能有一個Looper對象,其內部有一個MessageQueue,所有消息都存放在這個隊列中。
新創建一個線程時,系統不會爲這個線程創建Looper,需要自己創建。Android在啓動時,爲主線程(UI 線程)創建一個looper 對象。
1.1 HandlerThread
public class HandlerThread extends Thread {
int mPriority;
int mTid = -1;
Looper mLooper;
public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}
public HandlerThread(String name, int priority) {
super(name);
mPriority = priority;
}
protected void onLooperPrepared() {
}
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();//Looper類的實例必須通過prepare函數創建
synchronized (this) {
mLooper = Looper.myLooper();//通過myLooper方法獲取Looper對象
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();//loop函數主要分發消息隊列中的消息。
mTid = -1;
}
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
}
下面我們主要看下Looper類中的loop方法:
public static void loop() {
final Looper me = myLooper();
... ...
final MessageQueue queue = me.mQueue;//消息隊列
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {//無線循環
Message msg = queue.next(); // might block
... ...
msg.target.dispatchMessage(msg);//分發消息
... ...
msg.recycle();
}
}
looper.loop() 就是在一個死循環中持續讀取MessageQueue 中的消息並dispatch。
Handler類
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
... ...
mLooper = Looper.myLooper();
... ...
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
Handler主要負責消息的發送和處理。在一個線程中可以只用一個Hander對象處理所以消息,也可以使用多個。
1.構造一個Handler對象,需要兩個參數,線程的Looper對象和消息處理函數,如果不指定looper,會使用當前線程的looper對象。
2.handler 對象創建時,調用的是當前線程的Looper對象作爲mLooper,同時調用mQueue = mLooper.mQueue , 即當前線程的消息隊列作爲自己將要處理的消息隊列(Handler.mQueue)。
3.並不是每個線程都默認有looper 對象,所以在創建handler對象之前,會先調用Looper.prepare(),爲當前Thread 創建一個looper 對象
Handler.sendMessage ->Handler.sendEmptyMessage ->... ->Handler.enqueueMessage
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;//注意msg.target都是handler,因此在消息線程的loop函數處理消息時,msg.target.dispatchMessage會回到handler。
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
所有的發送消息接口,最後都會調用MessageQueue類中enqueueMessage函數,參數除了消息外,就是一個時間。而MessageQueue類中enqueueMessage函數只是把消息插入到消息隊列中的合適位置。
總結一下:
0. 一個線程有且僅有一個looper對象,looper對象中有一個MessageQueue 作爲消息隊列;
1.消息機制需要一個線程環境,裏面需要一個Looper對象,並且在線程的run函數中調用Looper.loop()函數;
2.函數需要一個handler來發送和處理消息。Hander要有一個Looper對象,來指定其線程,還要實現handleMessage函數。
Looper線程首先是一個Thread,由Java 標準線程變化過來:
一般的:
class LooperThread extends Thread { //繼承Thread 類
public Handler mHandler; //需要一個handler對象發送處理消息
public vold run { //實現run() 方法
Looper.prepare(); //Looper線程準備階段
mHandler = new Handler() { //初始化消息處理器
public vold handleMessage (Message msg) {
//TODO :處理消息
}
};
Looper.loop(); //Looper線程循環階段
}
}
以上代碼可知,Looper線程實際上繼承了Thread 類,並實現run 方法,運行run()時:
1.調用Looper.prepare爲當前thread 創建一個Looper對象(一個線程有且僅有一個looper 對象);
2.創建handler對象,將之前創建的looper 對象的MsgQueue作爲自己的MsgQueue ,負責分發和處理消息;
3.調用Looper.loop()方法進入Looper線程循環階段;
4.handler 發送消息最後調用MessageQueue類中enqueueMessage函數,就是把消息插入到消息隊列中的合適位置