Looper java
Looper的構造方法是private的,不能夠在外部生成Looper的實例. 緩存
最重要的幾個變量: 安全
ThreadLocal :靜態的,保存全部線程及其所關聯的Looper實例.能夠理解爲這是一個Map,保存了線程->Looper的全部鍵值對.這裏能夠獲取到全部的線程及其關聯的Looper對象.當咱們須要生成一個支持消息循環特性的Thread時,系統就把它相關的系統註冊進了這個ThreadLocal表中,因此ThreadLocal維護着全部線程及其Looper. oop
Looper mMainLooper:靜態的, 全局的與主線程關聯在一塊兒的Looper. post
MessageQueue mQueue: 非靜態的,消息隊列實例.即每一個Looper都有一個消息對列. 性能
Thread mThread:非靜態的,與Looper實例相關的那個線程. spa
最重要的幾個方法: .net
prepare():當在某線程內調用此方法時,則會分配一個Looper對象給此線程,而且把它們註冊進公共的靜態的ThreadLocal對象中. 線程
loop():這裏就進入了消息循環.在循環裏面一直調用MessageQueue.next()方法從消息隊列中取Message,若是隊列爲空,則它會一直阻塞着.直到有Message到來,拿出來後由這個Message關聯的Handler.dispatchMessage(Message)進行分發,最終的具體處理以下: code
若是此Message關聯的callback(Runnable類型)設置了,則運行它的run方法;
不然,檢查發送此Message的Handler的callback,若是有,則運行它的handleMessage方法;
最後若是都爲空,則運行Handler自己的handleMessage方法,這個方法的默認實現是留空的,因此咱們一般是繼承Handler類,而後重寫此方法,這也是咱們平時最常使用的一種方式.
建立一個帶消息循環功能的Thread的基本方法:
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare();//給此線程分配一個Looper,並註冊入ThreadLocal表 mHandler = new Handler() { public void handleMessage(Message msg) { // 處理Message消息 } }; Looper.loop();//開始從MessageQueue中取Message消息,進行消息循環. }
Handler
Handler在默認狀況下,與實例化它的那個線程就關聯在一塊兒了,這樣也就與此線程關聯的Looper及MessagQueue關聯在一塊兒了.Handler的基本做用就是經過post(Runnable) 和sendMessage(Message)之類的方法,往MessageQueue發送Message消息.而最終消息從MessageQueue中取出後按上面分析Looper時說明的方式進行處理.
Message
Message是做爲承載消息的實例,是一個很重要的對象,它必須與某個Handler相關聯在一塊兒.在構造實例時一般要指定它的目標Handler(源代碼中用target變量來引用的).
要獲得一個Message實例,雖然能夠經過此的構造方法來生成,但一般不這樣作,而是經過Handler類的obtainMessage()方法或Message類的obtain(Handler h)方法,由於這樣系統會全局緩存Message實例,經過在緩存池中就能夠拿出一個Message對象,提升性能.
最後要注意幾個對象的callback:
Message對象能夠設置Runnable類型的callback,MessageQueue中處理消息時優先使用Message本身的callback.
Handler對象也能夠設置Handler.Callback類型的callback,若是Message本身沒有設置callback,則用這個callback處理消息.其實這個接口定義的方法爲
abstract boolean handleMessage(Message msg)
與Handler自己裏面處理消息的方法僅返回值不一樣.
void handleMessage(Message msg)
若是以上兩個callback都沒有設置,就只能由Handler自己的handleMessage方法來處理消息了.
對象之間的關係:
理解Android消息循環機制的關鍵上理清以上幾個對象的關係,清楚哪一個對象包含哪些對象後就不難明白運行機制了.
Looper包含與它關聯的Thread和MessageQueue; 另外還有一個靜態的註冊表ThreadLocal.
Handler包含與它關聯的Looper,同時這樣間接關聯了Thread和MessageQueue,也就能夠經過post(Runnable) 和sendMessage(Message)往MessageQueue中發Message了,其實Handler必須與一個且僅一個線程綁定.
Message包含了發送它的Handler.
動態運行過程:
一個線程啓動運行,調用Looper.prepare()靜態方法,建立一個Looper實例和MessageQueue,與它們綁定,並把本身登記入註冊表(ThreadLocal),接下來又建立了若干個Handler實例,使Handler與本身及MessageQueue綁定.而後調用Looper.loop()靜態方法,啓動消循環,線程不斷從MessageQueue裏取出Message並處理之.
同時,另外的線程運行過程當中,調用Handler的post(Runnable) 和sendMessage(Message)族的方法往MessageQueue裏發Message.這樣兩個線程就經過Message進行了通訊.
詳細分析能夠發現,經過Handler發送Message的線程實際上是知道本身發送的Message的詳細狀況,其實也是能夠本身直接處理Message的(即執行Handler.handleMessage()方法裏的邏輯),但它爲何要兜這麼大一個圈子呢?緣由就在於,它要在目標線程裏執行業務邏輯,而不是在本身線程裏面執行.更深層次的緣由在於Android的UI線程不是安全的,其它線程須要修改UI線程包含變量時,爲避免同步問題,應該經過與UI線程綁定的Handler來發送處理命令到UI線程的MessageQueue裏,讓UI線程本身撿起來處理.這樣就避免了線程同步問題,同時也達到了目的.
參考:
http://blog.csdn.net/innost/article/details/6055793
http://blog.csdn.net/liuhe688/article/details/6407225