在建立handler時,handler在其構造方法中***嘗試從當前執行緒(建立hanlder例項物件的執行緒)的threadlocal中取到looper物件***,並將該looper物件賦值給當前hanlder物件,同時還會將looper物件的messagequeue引用賦值給當前handler。
public
static
@nullable looper mylooper()
//new handler()
public
handler
(callback callback,
boolean async)
mqueue = mlooper.mqueue;
mcallback = callback;
masynchronous = async;
}
在子執行緒中嘗試建立handler物件時,檢測當前執行緒是否已經關聯looper物件,不存在就報錯(需要呼叫looper.prepare()進行關聯),存在的話直接返回當前執行緒關聯的looper物件,使handler持有looper和looper.messagequeue的引用,從而能夠往messagequeue中新增訊息。乙個執行緒最多只能建立乙個looper,但是多個handler可以對應同乙個looper,只要在乙個執行緒中。
private
static
void
prepare
(boolean quitallowed)
sthreadlocal.
set(
newlooper
(quitallowed));
}
在主線程中建立handler不需要手動呼叫looper.prepare(),因為主線程的activitythread變數在main方法中呼叫了preparemainlooper()來初始化了主線程的looper物件。
public
static
void
main
(string[
] args)if(
false
) looper.
loop()
;}
handler的sendmessage呼叫的是messagequeue.enqueuemessage(message,uptimemillis),因為可能存在多個執行緒同時往同乙個messagequeue中插入message,所以messagequeue.enqueuemessage是同步方法。sendmessage()最終呼叫sendmessageattime(),只不過它的uptimemillis引數為0,即不延時執行的意思。
public
final
boolean
sendmessage
(message msg)
public
final
boolean
sendmessagedelayed
(message msg,
long delaymillis)
return
sendmessageattime
(msg, systemclock.
uptimemillis()
+ delaymillis)
;}
這裡的uptimemillis隨msg存入到mq,而sendmessagedelayed()的延遲執行效果是有mq在取出訊息進行dispatch時完成的,取出訊息時會比對當前時間和msg的when屬性。
public
boolean
sendmessageattime
(message msg,
long uptimemillis)
return
enqueuemessage
(queue, msg, uptimemillis);}
private
boolean
enqueuemessage
(messagequeue queue, message msg,
long uptimemillis)
return queue.
enqueuemessage
(msg, uptimemillis);}
boolean
enqueuemessage
(message msg,
long when)
if(msg.
isinuse()
)synchronized
(this
) msg.
markinuse()
; msg.when = when;
message p = mmessages;
boolean needwake;
if(p == null || when ==
0|| when < p.when)
else
if(needwake && p.
isasynchronous()
)}msg.next = p;
// invariant: p == prev.next
prev.next = msg;
}// we can assume mptr != 0 because mquitting is false.
if(needwake)
}return
true
;}
looper呼叫loop()方法,其中不斷從messagequeue中取出message(通過message.next()方法),進行dispatchmessage,其實在handler呼叫sendmessage時已經將自己設定為message.target了,所以dispatch只是將message發給自己的target處理而已。
定義乙個全域性的handler物件mhandler;在子執行緒a中初始化這個mhandler,並重寫handlermessage()方法;在子執行緒b中呼叫mhandler.obtainmessage()方法從message類自帶的message pool中返回乙個message物件,然後使用message.sendtotarget()方法,傳送訊息。
public
static
void
loop()
...}
...}
首先需要知道造成anr的原因:
當前的事件沒有機會得到處理(即主線程正在處理前乙個事件,沒有及時的完成或者looper被某種原因阻塞住了)。
**當前的事件正在處理,但沒有及時完成。**執行時間超過了anr的閾值:按鍵事件 5s ,broadcast 10s、前台service無響應的超時時間為20秒,後台service為200秒。
這樣就可以解釋為什麼主線程的looper.loop()一直無限迴圈但是為什麼沒有造成anr了,從上面的**可以看出當沒有message需要處理時,主線程沒有進行任何和造成anr有關的事件的處理,雖然是在無限迴圈,但是比起頻繁的開啟、關閉訊息迴圈動作,這樣的開銷反而更小吧。
Android訊息傳遞之元件間傳遞訊息
前言 上篇學習總結了android通過handler訊息機制實現了工作執行緒與ui執行緒之間的通訊,今天來學習一下如何實現元件之間的通訊。本文依然是為學習eventbus做鋪墊,有對比才能進步,今天主要介紹在eventbus出現之前的實現方式,通過intent方式這裡不做介紹。需求場景 方式一 通過...
Android 訊息傳遞機制分析
android系統出於系統優化的原因,ui執行緒操作並不是執行緒安全的,這意味著如果多執行緒併發操作ui元件,則可能導致執行緒執行緒安全。所以為了解決這個問題,android制定了一條規則 只允許ui執行緒修改activity裡的ui元件。當乙個程式啟動第一次啟動時,android會同時啟動一條主線...
Android中Handler訊息傳遞機制
因為是在專案中的收穫,所以不全,以後遇到其他的我會加上。安卓中用handler機制來實現主線程和子執行緒之間的通訊,通訊的媒介是message的例項。首先要在主線程宣告乙個handler物件,然後重寫裡面的handmessage message msg 方法,用switch case語句進行匹配處理...