又又又要找工作了ε=(′ο`*)))唉,寫一下自己對handler的一些認識吧,方便日后面試的時候去看。
Android消息機制概述
Android的消息機制主要是handler的運行機制以及Handler所附帶的MessageQueue和Looper的工作過程,這三者實際上是一個整體,只不過在開發中接觸的比較多的是Handler而已。
小知識:為什么系統不允許在子線程訪問UI呢?因為Android的UI控件是線程不安全的。為什么不對UI控件的訪問添加上鎖機制呢?首先添加鎖機之后會讓UI操作變得很復雜,其次會降低UI的訪問效率。
當Handler創建完之后,Looper與MessageQueue就可以一起愉快的玩耍了。
ThreadLocal是什么?
ThreadLocal是線程內部的一個數據儲存類,通過他可以在指定的線程中存儲數據,數據存儲后只有在指定線程中才能獲取到存儲的數據。
一般應用場景為:當某些數據是以線程為作用域并且不同的線程有不同的副本時,可以考慮使用ThreadLocal。
消息隊列的工作原理
MessageQueue主要包含兩個操作:插入、讀取。讀取本身還伴隨著刪除操作,插入和讀取對應的方法為:enqueueMessage和next。雖然他是叫消息隊列,但是卻是一個單鏈表的數據結構,單鏈表在插入和刪除上比較有優勢。next是一個無限循環的方法,如果消息隊列沒有消息就會一直組賽在這里,當有消息來的時候,next會返回這條消息并將其從單鏈表中移除。
Looper的工作原理
Looper在Android中扮演著消息循環的角色,具體來說他會一直不停地從MessageQueue中查看是否有新的消息。如果有就取出,否則就一直阻塞在那里。他的構造方法會穿件一個MessageQueue,然后將當前線程的對象保存下來。在子線程中想要創建Looper可以通過Looper.perpare()創建一個新的Looper,緊接著通過Looper.lope()來開啟消息循環。除了上述方法外,Looper還提供了一個gerMainLooper的方法來獲取到主線程的Looper。
Looper也是可以退出的,它提供了兩種方法:quit和quitSafely。二者的區別是quit會直接退出,quitSafely是會設定一個退出標記,當消息隊列數據處理完后安全退出。所以當子線程創建了Looper后一定要記得退出,否則這個線程會處于等待狀態。
Looper最重要的方法就是loop方法,它會調用MessageQueue的next方法來獲取新的消息,二next是一個阻塞操作,當沒有消息時next會一直阻塞在哪里,這也導致loop方法阻塞。如果next返回了新的消息,Looper會處理這條消息。當next返回一個null時則會跳出死循環。
Handler的工作原理
Handler的主要工作就是消息的發送和接受。消息發送可以通過post與send的一系列方法來實現,post最終是通過send方法來實現的。
當handler想消息隊列中插入一條消息時,MessageQueue就會調用next方法將這條消息給Looper,Looper接收到消息后就交由handler來處理了,即Handler的dispatchMessage方法會被調用,這時Handle就進入消息處理階段了。最后調用handler的handleMessage方法來處理。
Handler還有一個特殊的構造方法,那就是通過一個特定的Looper來構造Handler,通過這個構造能實現一些特殊的功能。
主線程的消息循環
Android得住線程就是ActivityThread,住線程的入口方法是main,在main方法中系統會通過Looper.prepareMainLooper()來創建主線程的Looper以及MessageQueue,并通過Looper.loop()來開啟循環。開啟循環后,ActivityThread還需要創建一盒Handler來和消息隊列進行交互,這就是ActivityThread.H,它的內部定義了一組消息類型,主要包含四大組件的啟動與停止的過程。