Handler消息機制
Message 消息
Message.obtain()
Message msg = new Message()
Handler
new Handler(){
handlerMessage(Message msg){
// 處理消息
}
}
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()");
}
mQueue = mLooper.mQueue;
mCallback = null;
}
主線程設置Looper,在ActivityThread類裏面
public static final void main(String[] args) {
....
// 1.主線程建立Looper
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
Looper
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 三、在主線程中設置Looper, new Looper()裏面建立了一個MessageQueue
sThreadLocal.set(new Looper());
public static final void prepareMainLooper() {
// 二、調用prepare
prepare();
setMainLooper(myLooper());
if (Process.supportsProcesses()) {
myLooper().mQueue.mQuitAllowed = false;
}
}
主線程調用Looper.loop()方法,主線程就會阻塞,是一個死循環,使用管道(Pipe),是Linux中的一種進程間通訊方式,使用了特殊的文件,有兩個文件描述符(一個是讀取,一個是寫入)
應用場景;主進程拿着讀取描述符等待讀取,沒有內容時就阻塞,另外一個進程拿寫入描述符去寫內容,喚醒主進程,主進程拿着讀取描述符讀取到內容,繼續執行。
Handler應用場景:Handler在主線程中建立,Looper會在死循環裏等待取消息,一、沒取到,就阻塞,二、一旦被子線程喚醒,取到消息,就把Message交給Handler處理。子線程用Handler去發送消息,拿寫入描述符去寫消息,喚醒主線程。
public static final void loop() {
...
while (true) {
// 取消息,若是沒有消息,就阻塞
Message msg = queue.next(); // might block
...
msg.target.dispatchMessage(msg);
...
}
}
Handler發送消息代碼
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
....
// 把Message的target置爲當前發送的Handler,以便Looper取到message後根據target把message分發給正確的Handler
msg.target = this;
// 往隊列裏面添加Message
sent = queue.enqueueMessage(msg, uptimeMillis);
....
}
MessageQueue.enqueueMessage 代碼
final boolean enqueueMessage(Message msg, long when) {
...
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
// 當前發送的message須要立刻被處理調,needWake喚醒狀態置true
msg.next = p;
mMessages = msg;
needWake = mBlocked; // new head, might need to wake up
} else {
// 當前發送的message被排隊到其餘message的後面,needWake喚醒狀態置false
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
needWake = false; // still waiting on head, no need to wake up
}
}
// 是否喚醒主線程
if (needWake) {
nativeWake(mPtr);
}
return true;
Handler.dispatchMessage方法
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
// 把Message交給Handler處理
handleMessage(msg);
}
}