概述:?
?????為了 線程間 通信方便, Handler 機(jī)制 通過 Handler 和 Looper, MessageQueue, Message 這些 類 之間的協(xié)作, 簡化 多線程的開發(fā). ?線程的交互 會被封裝 到 Message 中, 然后 通過 Handler 的方法 把 消息 放到 MessageQueue 消息隊列中, 實(shí)現(xiàn) Handler 機(jī)制的線程 都會 調(diào)用 Looper 的 loop() 方法, 則 Looper 作為 消息分發(fā)者的 作用就體現(xiàn)出來了. ?loop() 方法中, 會 從消息隊列 MessageQueue 中 獲取 Message, 然后 將 獲取到的Message 丟給 負(fù)責(zé) 處理消息的 Handler . ?Handler 再 ?根據(jù) Message 中的 callback(Runnable) 是否為 空 以及 Handler 中的 回調(diào) mCallback(Handler.Callback) 是否為空 來決定 最終交給 哪個 方法進(jìn)行消息處理.?
-----------------------------------------------------------------------------------------------------------------------
Handler 機(jī)制中, 各個角色的分工如下:
1. Handler : ?負(fù)責(zé)消息(Message) 的發(fā)送 和 處理
2. Looper : 負(fù)責(zé) 消息的 分發(fā)
3. MessageQueue : 負(fù)責(zé)消息的 管理
4. Message : ?帶有 int 型參數(shù) what 以及 arg1 和 arg2,這些是為了 簡化 通過 setData(Bundle bundle) 設(shè)置的 數(shù)據(jù), ?以及 一個 任意 對象的 參數(shù) obj. ?如果期望的 話 還 可以 帶一個 Runnable 類型的參數(shù) callback,
--------------------------------------------------------------------------------------------------------------------
第一部分: ?Handler?
Handler 的創(chuàng)建 ?:?
?1. ?如果 參數(shù) 有 Looper 則 把 Looper 賦值給 mLooper 否則 則 把 當(dāng)前 線程 對應(yīng)的 Looper 賦值給 mLooper. ? ?2. ? 獲取 Looper 對應(yīng)的 消息 隊列 mQueue. ? 3. ?如果 構(gòu)造函數(shù)的參數(shù)中 包含 Handler.Callback 的 實(shí)例 callBack 則 把其 賦值給 mCallback 變量.
Handler 消息的發(fā)送: ?
1. 要 發(fā)送的消息 內(nèi)容 有 兩種 ?一種 ?Runnable ?另一種 ?Message.
通過 跟蹤 post 的實(shí)現(xiàn), 則 可以發(fā)現(xiàn) Runnable ?也 被 轉(zhuǎn)化 為 Message 對象了.
圖1:圖2:
2. ?消息發(fā)送 調(diào)用的 常見方法有 : ?post(Runnable), postDelayed(Runnable,long), 以及 sendEmptyMessage(int), sendMessage(Message) , sendMessageDelayed(Message,long) 這些方法都會 歸宗于 : sendMessageAtTime()?
在 sendMessageAtTime 中 主要 是把 ?Message 對應(yīng)的 target 參數(shù) 設(shè)置為 當(dāng)前 Handler, 然后 把 此 msg 放入 MessageQueue 隊列中,
3. 消息 處理時 對應(yīng)的方法回調(diào):
handle 消息 處理的位置 有 三處:其1: ?當(dāng) 消息為 Runnable 消息的時候, 則 msg 的 callback (即 Runnable 對象) 是不為 空的, 則 直接 調(diào)用 ?msg.callback.run() 執(zhí)行 回調(diào).其2: 當(dāng)我們在 構(gòu)造 Handler 的時候 有 傳入 Handler.Callback 回調(diào)對象的時候, 則 mCallback 不為空( 由 Handler 的構(gòu)造函數(shù) 可知), 則 調(diào)用 Handler.Callback 這個 接口 對應(yīng)的 handleMessage() 方法.?其3: 如果 沒有前面 兩種, 則 在 創(chuàng)建 Handler 的 子類 或者 匿名對象的時候 會 重載 handleMessage 來 處理對應(yīng)的 回調(diào)邏輯.
第二部分: Looper?
?looper 的初始化:
當(dāng) 調(diào)用 Looper 的靜態(tài) 方法 prepare() 的時候則 會創(chuàng)建 一個 Looper 對象, 并設(shè)置 到一個 靜態(tài)的縣城局部變量中去.在 Looper 的構(gòu)造函數(shù)中, 可以看到 會創(chuàng)建 一個 MessageQueue 對象, MessageQueue 作為 消息隊列.
Looper.loop() 方法的調(diào)用
?一個線程 調(diào)用 prepare() 只是 準(zhǔn)備好了消息隊列, 進(jìn)入 消息隊列的 等待, 則是 調(diào)用 Looper 的 loop() 方法:透過 loop() 方法的實(shí)現(xiàn), 可以知道 首先從 當(dāng)前 線程對應(yīng)的 Looper 中 獲取到 對應(yīng)的消息 隊列, 然后 從 消息 隊列中 獲取 下一條 要執(zhí)行 的 message, 當(dāng) 獲取到的 Message 為 null 的時候則 直接退出循環(huán).?如果 msg 不為null, 則 調(diào)用 Message 中 對應(yīng)的 Handler 對象的 ?dispatchMessage 方法 進(jìn)行消息的分發(fā). 消息的具體分發(fā) 已在上面 講過了.在 queue.next() 語句的 上面 可以 看到 for 循環(huán) 是一個 死 循環(huán), 則 可以知道 當(dāng) ?線程 調(diào)用 loop() 方法之后 就不會 繼續(xù)往 下執(zhí)行, 而 是在 等待 消息列表(queue) 返回消息 , 然后 將 ?消息 丟給 Handler 進(jìn)行處理.