1. 程式人生 > >android中handler和looper的工作原理

android中handler和looper的工作原理

在android中,UI執行緒和其他子執行緒之間傳遞資料一般要用到handler和looper,那麼其工作原理是 什麼呢?

我們通用的方法是:在UI執行緒中建立handler--將handler傳遞到子執行緒中--在子執行緒中sendmessage---訊息被載入進looper的message佇列中--在UI執行緒中handlemessage

該方法我們可以用一個比喻:

Handler在某個國家(主looper執行緒)例項化以後,就在該國家建立一個機構,該機構會派遣人員(handler)到某個子執行緒,該人員身上帶著訊息鴿子(obtainmessage),這些訊息鴿子的目的地(target)自動鎖定那個handler機構,當收集到訊息後,將訊息鴿子放出去(sendmessage)

,鴿子飛到後會把訊息放進訊息池(messageQueue)中,這個國家的looper會執行loop()方法,不停從訊息池中拿到訊息交給機構,機構得到訊息之後,有handleMessage()方法可以處理這些訊息;

但是,我們能不能在子執行緒中建立handler,實現UI執行緒的修改呢?
當然可以!直接派遣looper到子執行緒,跟那裡的handler繫結(通過handler的構造方法將looper傳進去),把在子執行緒例項化的handler變成主執行緒直屬handler來為自己服務,這樣在子執行緒的handleMessage方法中執行UI執行緒的修改也是不會報錯的。

那麼,到底是什麼機制,使這兩種方法都能行得通?

通過研究android原始碼之  handler.java  ~~ Looper.java,我們可以得到以下結論:

handler在哪裡建立是沒有關係的,重要的是handler傳送的message到達了那個looper的訊息佇列,不管通過什麼方法,只要讓handler傳送的訊息到達UI執行緒Looper的訊息佇列,就能實現對UI執行緒的修改!

要理解上面這句話,首先要了解這麼幾個概念:

1,一個普通Thread不能建立handler的,需要在該執行緒的run()方法中執行Looper.papare(),將該執行緒變為looperThread。(UI執行緒自動執行了looper.papare和looper.loop()方法,所以UI執行緒本身就是looper執行緒)
2,一個looperThread只能有一個looper,一個looper繫結一個messageQeue;
3,一個looperThread可以用多個handler;

handler跟Thread沒有關係,它跟looper繫結,具體繫結那個looper,就要看用的那個構造方法,如果用的是new Handler()這個構造方法,會預設繫結它所線上程的looper和訊息佇列(handler.java原始碼中描述為:mLooper = Looper.myLooper();mQeue = mLooper.Qeue),如果用的是new Handler(Looper looper)的構造方法,就會與傳進去的那個looper繫結;

繫結某個looper,當sendMessage時就會向那個looper繫結的訊息佇列(messageQeue)裡傳送訊息。

(那麼handlerMessage()這個方法是在哪裡執行的呢?)

Looper裡有個死迴圈方法loop(),不斷檢查與其繫結的訊息佇列裡的訊息,一條條按順序拿出,並執行msg.target.dispathMessage(msg),這個dispathMessage本身呼叫的就是handleMessage()方法,所以,handlerMessage本質上是在Looper的死迴圈裡處理的,只要這個Looper屬於UI執行緒,那麼程式就不會報錯,可以順利執行。

====================================================================================================================================

上面描述的是子執行緒操作UI時報錯的解決辦法,那麼子執行緒操作UI就一定會報錯崩潰嗎?

不!首先我們要了解系統為什麼會崩毀並報錯,是系統本身有一個判斷機制,當執行到layoutRequset  時,只有判斷到parentLayout != null系統才會判斷並丟擲異常,導致錯誤;

其實,在oncreate()方法中執行對UI控制元件值的修改是可以的,因為此時activity的生命週期才剛開始,parentLayout還沒建立和繪製,其值是null,所以“監控失效”,所以不會拋錯和崩潰,並且控制元件的屬性值會被正常修改。