我們知道,當應用啟動的時候,android首先會開啟一個主線程,主線程管理ui控件,進行事件分發,當我們要做一個耗時的操作時,如聯網讀取資料,擷取讀取本地較大的檔案的時候,你應該在子線程中操作,因為有ui的更新,android主線程是線程不安全的,如果将更新界面放在子線程中是危險的,必須在主線程中執行,這個時候引出Handler,Handler運作在主線程,他與子線程通過message對象來傳遞資料.
Message類
Message類: 用來攜帶資料的載體
public int what; //辨別
public int arg1; //攜帶int類型資料
public int arg2; //攜帶int類型資料
public Object obj;//攜帶任意對象資料
long when; //儲存要被處理的時間點
Handler target; //處理消息的handler
Runnable callback; //處理消息的回調器對象
Message next; //用來儲存引用的下一個message(才能形成連結清單)
private static Message sPool; //存儲處理過的消息的池 //在需要Message對象時複用
Message.obtain();//從消息池中擷取空消息對象
說明:
1.我們要擷取空消息對象時最好通過Message.obtain()方法從消息池中取消息,而不是它的構造器,這樣可以更好的複用消息對象,以節約記憶體。
2.如果Message要攜帶int型的資料時,可以使用它的arg屬性
3.Message 中的target即為處理消息的handler
4.what 為辨別資訊類别
Handler類
sendMessage(Message msg);
sendEmptyMessage(int what);
sendMessageDelayed(Message msg, long delayMillis)
sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);//目前時間+延遲時間
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this; //處理消息Handler就是發送消息的handler
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis); //将消息添加到消息隊列中
}
public final void removeMessages(int what) { //移除隊列中未被處理的消息
mQueue.removeMessages(this, what, null);
}
public void dispatchMessage(Message msg) {
if (msg.callback != null) { //如果message内部有回調處理器, 直接交給它處理
handleCallback(msg);
} else {
if (mCallback != null) {//如果Handler内部有回調處理器, 交給它處理, 如果傳回true才結束, 否則繼續
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg); //調用Handler的回調方法處理
}
}
需要注意的是:
1.handler可以在任意線程發送消息,這些消息都将添加到MessageQueue中
2.handler實在關聯了looper的線程中處理消息的,當然主線程也是一個looper線程
MessageQueue
enqueueMessage(Message msg, long when) {
msg.when = when; //将消息被處理的時間儲存在msg上
//将msg對象儲存到mMessages連結清單中一個合适的位置
nativeWake(mPtr); //喚醒處理等待狀态下的程式
//不是通過wait()來實作的, 而是通過C/C++的代碼來實作的, 不會阻塞主線程
}
Message next() { //從消息隊列中取出需要處理的消息, 如果沒有進入等待狀态(沒有阻塞主線程)
}
Looper
looper線程的建立
public class LooperThread extends Thread {
@Override
public void run() {
// 将目前線程初始化為Looper線程
Looper.prepare();
...
// 開始循環處理消息隊列
Looper.loop();
}
}
looper的一些屬性
public class Looper {
private static final ThreadLocal sThreadLocal = new ThreadLocal();// 每個線程中的Looper對象其實是一個ThreadLocal
final MessageQueue mQueue;// Looper内的消息隊列
Thread mThread;// 目前線程
private Looper() { // 建立Looper對象中的消息隊列,和它所屬的線程
mQueue = new MessageQueue();
mRun = true;
mThread = Thread.currentThread();
}
建立looper對象方法
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
static void loop() {
final MessageQueue queue = me.mQueue; //拿到消息隊列
Message msg = queue.next();// might block 從隊列中取出目前需要處理的消息
}
//将message對象交給handler分發處理
msg.target.dispatchMessage(msg);
msg.recycle(); //回收處理過消息: 清理内部資料, 并添加為消息池的第一個消息
這樣我們就把消息隊列中的幾個重要的對象簡單的過了一邊。