轉(zhuǎn)載一篇Handler機(jī)制文章以加深理解
http://blog.csdn.net/sinat_23092639/article/details/52334398
核心內(nèi)容提要:
1白热、Handler就是一個(gè)和創(chuàng)建當(dāng)前Handler對(duì)象的線程和線程的消息隊(duì)列綁定的組件垂谢。
2驶社、Looper是針對(duì)某個(gè)線程開啟消息循環(huán)撑螺,線程是默認(rèn)沒(méi)有消息循環(huán)的木蹬,要調(diào)用prepare來(lái)為當(dāng)前線程設(shè)置一個(gè)Looper强重,調(diào)用loop開啟消息循環(huán)直到循環(huán)結(jié)束為止礼旅。
3庆揩、核心代碼分析
public Handler(Callback callback, boolean async) {
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 = callback;
mAsynchronous = async;
}
(1)Handler不能沒(méi)有Looper俐东,否則報(bào)異常。
(2)Looper對(duì)象持有MessageQueue引用订晌。
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
(1)一個(gè)線程只能擁有設(shè)置一個(gè)Looper對(duì)象
(2)將Looper對(duì)象設(shè)置到ThreadLocal內(nèi)
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
(1)獲取ThreadLocal內(nèi)的Looper對(duì)象
4虏辫、消息發(fā)送機(jī)制
sendMessage
sendMessageDelay
sendMessageAtTime
enqueueMessage 【最終調(diào)用】
5、獲取消息
loop循環(huán)提取MessageQueue隊(duì)列內(nèi)的消息
6锈拨、總結(jié):
一個(gè)線程對(duì)應(yīng)一個(gè)Handler砌庄,因?yàn)镠andler的構(gòu)造函數(shù)內(nèi)獲取的是綁定了該線程的Looper;
一個(gè)線程只能一個(gè)Looper對(duì)象奕枢,從而只有一個(gè)MessageQueue(在Looper的構(gòu)造方法初始化)娄昆;
所有的線程共享同一個(gè)ThreadLocal對(duì)象,不同線程向ThreadLocal對(duì)象設(shè)置的Looper不同缝彬;
這里的關(guān)鍵還是ThreadLocal類萌焰,它可以在Handler對(duì)象需要與Looper對(duì)像關(guān)聯(lián)的時(shí)候提供當(dāng)前;
線程的關(guān)聯(lián)的Looper谷浅,并從該Looper得到當(dāng)前線程的消息隊(duì)列引用扒俯,從而使得Handler對(duì)象在發(fā)送消息的時(shí)候可以發(fā)送到創(chuàng)建自己的線程的消息隊(duì)列。而
此時(shí)該線程的Looper消息循環(huán)執(zhí)行Message的時(shí)候已經(jīng)在創(chuàng)建Handler的線程中一疯;
使用靜態(tài)的Handler對(duì)象避免出現(xiàn)內(nèi)存泄漏撼玄。