Handler, Message 消息傳遞機制
個人了解
在建立handler之前,必須确認已經在handler所線上程中調用了Looper.prepare(),因為在handler構造函數中會判斷目前線程中是否有Looper對象,沒有則報異常(無法在沒有調用Looper.prepare()的線程中建立handler對象)
Looper.prepare作用:
1:判斷目前線程中是否存在Looper對象,否則new一個ThreadLocal類型Looper對象,使得每個線程有獨立的Looper,防止多線程傳遞消息時發生異常,是則報異常(一個線程中最多隻能有一個Looper對象)。在Looper構造函數中建立了消息隊列對象mQueue。
2:即1中建立了消息隊列對象mQueue,将Looper和MessageQueue的對象“綁定”在一起。
在handler構造函數中,将handler所線上程中的Looper所建立的消息隊列對象mQueue指派給handler中聲明的消息隊列對象mQueue,将Looper,Handler,MessageQueue的對象“綁定”在一起。
發送消息:
Handler發送消息msg的方法經過封裝調用最後跳轉到sendMessageAtTime(Message msg, long uptimeMillis)方法(除了sendMessageAtFrontOfQueue(),這個方法将新的message放置到消息隊列的頭部),在其内部調用enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)方法,将handler中聲明的消息隊列mQueue傳入,通過msg.target = this, 将調用發送消息方法的handler對象(即this)與所發送的消息“綁定”,繼續調用enqueueMessage的2個參數的方法,将傳入的消息以隊列排列。
接下來要取出消息隊列中的消息,通過Looper.loop()方法實作,獲得目前線程中的Looper對象,取出它的消息隊列,通過for(;;)死循環取出隊列中的消息,并調用msg.target.dispatchMessage(msg)方法(msg.target即是與發送消息“綁定”的handler),将取出的消息傳回handler所線上程的handlemessage(msg)方法中,在裡面更新UI,完成非UI線程和UI線程間的通信,解決因線程不安全不适合在非UI線程更新UI的問題。