Handler Looper Message

首先,他們仨是啥?先簡單總結(jié)一下:

1.Looper?

負(fù)責(zé)在所給定線程里run起一個消息循環(huán),往簡單說它就弄了個死循環(huán),不停在message queue里取消息,有消息就處理消息,沒消息就阻塞

這一切是在Loop.loop()實現(xiàn)的,注意,它是這個類的靜態(tài)方法,簡單看一下這個方法的實現(xiàn),我摘取了重要的幾行:

public static Looper myLooper() {

return sThreadLocal.get();//ThreadLocal類,對不同線程不同實例的類,這里對ThreadLocal類的應(yīng)用也是Looper設(shè)計的精髓所在

}

public static void loop() {

final Looper me = myLooper();//獲取當(dāng)前線程的Looper對象

final MessageQueue queue = me.mQueue;

for (;;) {//死循環(huán)

Message msg = queue.next(); // might block阻塞在這里面實現(xiàn)

if (msg == null) {

// No message indicates that the message queue is quitting.

return;

}

msg.target.dispatchMessage(msg);//target就是handler

msg.recycleUnchecked();//回收Message對象,將屬性歸零,將此message對象作為鏈表頭

}

}

另一個重要的static方法,Looper.prepare(),其實就是為當(dāng)前線程創(chuàng)建一個Looper對象

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));

}

2.Message

本質(zhì)上是個鏈表,next對象指向message池中的第一個可用message,至于為啥要節(jié)約使用message對象,要弄個緩存池我沒理解

其中MessageQueue被Looper引用,當(dāng)next方法被調(diào)用時,使用nativePollOnce實現(xiàn)無消息時的阻塞

3.Handler

起到分發(fā)和處理的作用,怎么知道哪個message給哪個handler處理呢?message里面的target屬性,就是指向處理者Handler。其比較重要的幾個方法:

A.構(gòu)造new Handler()會獲取當(dāng)前線程所在looper對象,那么就有個要求啦,必須是一個prepare過的Looper,因為如果不prepare過,那當(dāng)前線程的looper對象是沒有建立的,這點對于主線程來說,在ActivityThread中早就調(diào)用過Looper.prepareMainThread(),因此主線程可以隨便new handler不會報錯,但是在其他線程就不能這么任性了。

B.sendMessage

其實就是把message放到message queue里面

C.obtainMessage

調(diào)用了Message.obtain()方法,新建或重用一個message對象

D.dispatchMessage & handleMessage

Looper的loop方法中調(diào)用dispatchMessage

一般都會重寫handleMessage方法來處理收到的message,如果message自帶callback那就用message自己的callback

其次,為啥會有經(jīng)典的內(nèi)存泄漏問題呢?

如果我們在Activity里面寫個子類MyHandler extends Handler,這樣呢就會遇到一個經(jīng)典的內(nèi)存泄漏問題啦

因為java的內(nèi)部類會持有對外部類的引用,而message對象的target又持有handler的引用,一旦我們發(fā)送一個延遲處理的消息,就會導(dǎo)致關(guān)閉Activity的時候無法回收Activity對象,從而造成泄漏啦。處理的方法,要么就寫成一個靜態(tài)內(nèi)部類,讓handler不要引用Activity,要么就在activity的onDestroy()方法里調(diào)用在activity的onDestroy()方法里調(diào)用handler.removeCallbacksAndMessages(null);把message神馬的都清空,就沒事了

再次,HandlerThread是個什么鬼?

其實它很簡單,它從源碼上看,和Handler沒啥關(guān)系,就是一個帶Looper的Thread,就這么簡單,那為啥叫HandlerThread呢?因為Handler要用它的Looper啊,就這么簡單的關(guān)系。

它能干點啥呢?排隊嘛,因為message是一個個的處理的,所以這個非常適合在work thread中需要一個個依序排隊處理請求的情況。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容