本篇主要介紹Android中的消息機制,即Looper、Handler是如何協同工做的;oop
Looper:主要用來管理當前線程的消息隊列,每一個線程只能有一個Looperpost
Handler:用來將消息(Message)插入到當前線程的消息隊列,並負責分發Looper中的消息,將消息發送到當前線程執行ui
具體關係圖以下所示:this
接下來咱們來分析一下Looper和Handler的源碼,瞭解一下其中的奧妙。spa
首先咱們從一個程序運行的入口來分析,源碼以下:線程
public static void main(String[] args){ ...... Looper.prepareMainLooper();//初始化Looper ...... if(smainThreadHandler==null){ smainThreadHandler=thread.getHandler();//初始化Handler } ...... Looper.loop();//消息循環執行 }
能夠看出,程序在運行的時候首先會建立主線程的Looper對象,並經過Looper開啓消息循環,不停的取出消息並執行;code
接下來咱們來研究Looper的源碼;對象
第一部分:Looper源碼blog
初始化接口
1 private Looper(boolean quitAllowed) { 2 mQueue = new MessageQueue(quitAllowed); 3 mThread = Thread.currentThread(); 4 } 5 6 初始化Looper對象(該過程包含初始化消息隊列和當前線程對象) 7 private static void prepare(boolean quitAllowed) { 8 if (sThreadLocal.get() != null) { 9 throw new RuntimeException("Only one Looper may be created per thread"); 10 } 11 sThreadLocal.set(new Looper(quitAllowed)); 12 }
能夠看出Looper在初始化的時候,首先會建立消息隊列,並經過sThreadLocal保存在當前的線程本地變量中;
再來看一下程序入口Looper.prepareMainLooper();//初始化Looper究竟執行了什麼
1 //初始化主線程的Looper對象 2 public static void prepareMainLooper() { 3 prepare(false); 4 synchronized (Looper.class) { 5 if (sMainLooper != null) { 6 throw new IllegalStateException("The main Looper has already been prepared."); 7 } 8 sMainLooper = myLooper(); 9 } 10 }
這裏有兩行關鍵的代碼:prepare(false);和sMainLooper = myLooper();
首先咱們來看prepare(false);即上面講到的 初始化Looper,能夠看看上面的源碼;
咱們來看sMainLooper = myLooper();
1 public static @Nullable Looper myLooper() { 2 return sThreadLocal.get(); 3 }
很是簡單,咱們上面提到在初始化Looper的時候會把Looper保存到當前線程的本地變量中,而這行代碼的意思
就是從線程本地變量中將looper取出來
有了Looper,程序怎樣才能運行?答案就在Looper.loop();//消息循環執行
1 public static void loop() { 2 final Looper me = myLooper();//獲得當前線程的Looper對象 3 if (me == null) { 4 throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); 5 } 6 final MessageQueue queue = me.mQueue;//獲得消息隊列 7 8 ...... 9 10 //執行消息循環 11 for (;;) { 12 Message msg = queue.next(); // might block 13 if (msg == null) { 14 // No message indicates that the message queue is quitting. 15 return; 16 } 17 msg.target.dispatchMessage(msg); 18 msg.recycleUnchecked(); 19 } 20 }
顯而易見,loop方法就是獲取到當前線程的Looper對象,並從中循環取出消息,並執行,程序就這樣跑起來了,具體是如何分發消息的
咱們將會在下面講解;
至此咱們至少應該明白,當主線程在執行的時候
一、初始化Looper,並將Looper保存的線程變量中
二、Looper在初始化的時候會建立消息隊列,並管理消息隊列
二、取出Looper,並從消息隊列中取出消息,循環執行
第二部分:Handler源碼
咱們知道Handler有兩種使用方式,一種是使用handler.post(Runnable r);另外一種是複寫handleMessage(Message msg)方法
複寫handleMessage(Message msg)方法很是簡單,Handler在消息分發的時候,直接回調該方法便可,咱們主要來研究第一種
1 public final boolean post(Runnable r) 2 { 3 return sendMessageDelayed(getPostMessage(r), 0); 4 }
看到這個咱們首先得明白getPostMessage(r)幹了什麼
1 private static Message getPostMessage(Runnable r) { 2 Message m = Message.obtain(); 3 m.callback = r; 4 return m; 5 }
能夠看出是將r封裝成了一個消息,r做爲該消息的回調;
咱們接着看:
1 public final boolean sendMessageDelayed(Message msg, long delayMillis) 2 { 3 if (delayMillis < 0) { 4 delayMillis = 0; 5 } 6 return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); 7 }
關鍵代碼在sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
繼續:
1 //獲得消息隊列 2 public boolean sendMessageAtTime(Message msg, long uptimeMillis) { 3 MessageQueue queue = mQueue; 4 if (queue == null) { 5 RuntimeException e = new RuntimeException( 6 this + " sendMessageAtTime() called with no mQueue"); 7 Log.w("Looper", e.getMessage(), e); 8 return false; 9 } 10 return enqueueMessage(queue, msg, uptimeMillis); 11 }
這段代碼主要就是獲取到消息隊列,有了消息隊列咱們接着看enqueueMessage(queue, msg, uptimeMillis);
1 //handler和msg創建關聯 2 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { 3 msg.target = this; 4 if (mAsynchronous) { 5 msg.setAsynchronous(true); 6 } 7 return queue.enqueueMessage(msg, uptimeMillis); 8 }
msg.target = this;這裏將msg的target指向本身,msg的target只能是this
最後相信你們也看出來了,接下來就是真正將msg插入到消息隊列了
1 //負責將msg插入到消息隊列 2 boolean enqueueMessage(Message msg, long when) { 3 if (msg.target == null) { 4 throw new IllegalArgumentException("Message must have a target."); 5 } 6 7 synchronized (this) { 8 //將msg插入到消息隊列 9 10 msg.when = when; 11 Message p = mMessages; 12 boolean needWake; 13 //消息隊列爲鏈式存儲 若是消息隊列中的消息爲0,將msg插入到第一個,並新建一個message對象,將 14 //msg對象的next指向新建的message 等待新msg插入 15 if (p == null || when == 0 || when < p.when) { 16 // New head, wake up the event queue if blocked. 17 msg.next = p; 18 mMessages = msg; 19 needWake = mBlocked; 20 } else { 21 //將msg插入到隊尾 22 for (;;) { 23 prev = p; 24 p = p.next; 25 if (p == null || when < p.when) { 26 break; 27 } 28 if (needWake && p.isAsynchronous()) { 29 needWake = false; 30 } 31 } 32 msg.next = p; // invariant: p == prev.next 33 prev.next = msg; 34 } 35 36 37 } 38 return true; 39 }
繞了這麼大一圈,最後是經過Handler中的消息隊列,將消息成功插入隊尾,至此handler在post的時候實際上
是將r封裝成了一個msg並插入到消息隊列;
另外這裏再提一下Handler第二種方式即複寫handleMessage(Message msg)方法使用
handler.sendMessage(msg);
其源代碼其實就是執行以上的
1 public final boolean sendMessageDelayed(Message msg, long delayMillis) 2 { 3 if (delayMillis < 0) { 4 delayMillis = 0; 5 } 6 return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); 7 }
重複以上一系列過程,將msg插入到消息隊列;
最後咱們來看一下比較關鍵的消息分發,消息分發是在以上Looper源碼的loop方法中核心方法是:
msg.target.dispatchMessage(msg);
咱們知道msg的target只能是Handler自己,所以消息分發是在Handler中來完成的;
1 /** 2 * Handle system messages here. 3 */ 4 public void dispatchMessage(Message msg) { 5 if (msg.callback != null) { 6 handleCallback(msg); 7 } else { 8 if (mCallback != null) { 9 if (mCallback.handleMessage(msg)) { 10 return; 11 } 12 } 13 handleMessage(msg); 14 } 15 }
第一:if (msg.callback != null) 若是你傳入了callback即Runnable,那麼就執行 handleCallback(msg);
即調用r的run方法,一般是handler.post(r);類型的
第二:if (mCallback != null)這種方法容許讓activity等來實現Handler.Callback接口,避免了本身編寫handler重寫handleMessage方法。
第三:handleMessage(msg); 即handler.sendMessage(msg);時調用的。直接回調Handler的handleMessage(msg);方法
至此,Android中的消息機制Looper和Handler相信你已經有了必定的瞭解;
最後咱們再來總結一下
一、Looper 一個線程中只能有一個Looper,用來管理消息隊列
二、Looper從消息隊列裏取出msg,交給Handler來進行分發,分發到Handler所在的線程執行,即建立Handler時的線程;
三、能夠在當前線程中建立消息對象或直接複寫Runnable的run方法,同過Handler將msg和r封裝後的msg插入到消息隊列