Android 之訊息機制

weixin_34194087發表於2018-06-07

Android的訊息機制主要是指Handler的執行機制,Handler的執行主要由MessageQueue(訊息佇列)和Looper(訊息迴圈泵)來支撐。MessageQueue只要儲存訊息,它是以佇列的形式對外提供刪除插入的工作,雖然是佇列 但它不是真正的佇列,底部還是採用的單連結串列的資料結構來儲存資訊列表的。由於MessageQueue只是一個訊息儲存單元,不會去處理訊息,這時候Looper就出現了,Looper就會以無限迴圈的形式去查詢是否有新訊息,如果有的話就會處理 ,如果沒有就會等待。 Looper中有一個重要的而有特殊的概念那就是ThreadLocal。

ThreadLocal是什麼呢?

它並不是執行緒,它的作用是可以在每個執行緒中儲存資料,Handler是如何獲取當前的Looper呢?這也需要ThreadLocal,ThreadLocal不僅可以在每個執行緒互不干擾的情況下儲存資料,還可以獲取每個執行緒的Looper。

這裡需要注意一個點就是執行緒預設可是沒有Looper的,如果使用Handler就必須為執行緒建立Looper。

我們經常提到的主執行緒也叫UI執行緒,他就是Activity Thread,ActivityThread被建立時就會初始化Looper,這也是主執行緒預設可以使用Handler的原因。下面就是Handler的工作過程圖

10436964-9b06bfdf414b2c69.png
Handler工作過程

Message Queue的工作原理

它的作用主要是插入和讀取。讀取的操作會伴隨著刪除功能。插入方法enqueueMessage,讀取方法next,next方法沒取出一條訊息並將其從佇列中移除。

Looper的工作原理

Looper在Android中扮演著訊息迴圈的角色,具體來說就是不停的檢視訊息佇列中是否有新的訊息,如果有新訊息就會被處理,否則會被阻塞 首先我們先看看它的構造方法

10436964-7e634e26b4f716e4.png
Looper構造方法

它的構造方法會建立一個Message Queue,然後再把當前的執行緒物件儲存起來。我們知道Handler的工作是需要Looper,沒有Looper的執行緒就會報錯,那麼如何為一個執行緒建立Looper呢?很簡單,就是呼叫Looper.prepare()方法來建立一個Looper,接著通過:Looper.loop()來開啟訊息迴圈的如下圖所示


10436964-11fcad45fddf8c40.png

Looper除了prepare方法外,還有prepareMainLooper方法,這個方法主要給主執行緒(ActivityThread)建立Looper使用的,其本質還是通過prepare方法實現的,這個Looper提供了getMain Looper方法,通過它可以在任何地方獲取到主執行緒的Looper,此外Looper也是可以退出的,通過quit和quitSafely來退出Looper,quit是直接退出,而quitSafely是做標記等到所有的訊息處理完後才安全退出。如果退出Looper 執行緒就會終止,所以不建議推出。

Looper中最重要的方法就是loop方法,只有呼叫了訊息系統才會起作用。

10436964-5815c858d851945e.png


10436964-d225218f44eb2f31.png

其實很好理解,loop方法是一個死迴圈,唯一跳出迴圈的方式是MessageQueue的next方法返回了null,怎麼返回null呢?當Looper的quit方法被呼叫時Looper就會呼叫quit方法或者quitSafely來退出訊息佇列,這是就會返回null。如果得到新的訊息就會通過msg.target.dispatchMessage(msg)方法處理訊息,msg.target是傳送訊息的Handler物件,這樣Handler傳送訊息就交給了dispatchMessage方法處理,而dispatchMessage方法是在建立Handler時所用的Looper中執行,所以就把邏輯程式碼切換到指定執行緒中執行了。

Handler的工作原理

Handler的工作主要是傳送訊息和接收過程,通過post和send方法來實現傳送訊息。

10436964-630c530124be8d14.png
10436964-2bda96c8deecfc10.png

Handler傳送訊息只是向訊息佇列中插入了一條訊息,Message Queue的next方法返回給Looper,Looper收到訊息處理再交給Handler處理,也就是dispatchMessage方法

10436964-1e7459d1bafcfc99.png
10436964-d0a9cef18d1ee87c.png

首先檢查Message的callback是否為null,如果不為null就通過handleCallback來處理,其實Message的callback是一個Runnable物件,實際上也是Handlerpost方法傳遞的Runnable引數。


10436964-c0fe6208b77cad2a.png

然後檢查嗎Callback是否為null,不為null就呼叫handleMessage方法來處理。Callback程式碼如下

10436964-eeed20dfb8b74995.png

通過Callback也可建立Handler物件:Handler handler = new Handler(callback)。

下圖是Handler的流程圖

10436964-740dd7e9c0fef36c.png
Handler訊息處理流程圖

這就是Android的訊息機制Handler


相關文章