第十章 Android的消息機制 面試中經常會被問到的一個問題:handler是如何在子線程和主線程中進行消息的傳遞的,這個問題通過瞭解Android的消息機制可以得到一個準確的答案。 Android的消息機制主要就是指Handler的運行機制,Handler的運行需要底層的Messa...
第十章 Android的消息機制
面試中經常會被問到的一個問題:handler是如何在子線程和主線程中進行消息的傳遞的,這個問題通過瞭解Android的消息機制可以得到一個準確的答案。
Android的消息機制主要就是指Handler的運行機制,Handler的運行需要底層的MessageQueue和Looper的支撐。需要理解兩個概念:
MessageQueue:消息隊列,通過單鏈表的數據結構來存儲一組消息,以隊列的形式對外提供插入和刪除的工作。
Looper:消息迴圈,以無限迴圈的方式查找MessageQueue是否有新消息,有的話就處理消息,否則一直等待。
如果需要使用Handler就必須為Handler所在的線程創建Looper,主線程在創建的時候會自動初始化Looper,而子線程預設是沒有Looper的,這就是在主線程預設可以使用Handler而子線程中預設不能使用Handler的原因。
Android系統之所以提供Handler,主要就是為瞭解決在子線程中無法訪問UI的矛盾。之所以不允許在子線程中訪問UI,主要是考慮到控制項不是線程安全的,因為多個線程訪問控制項可能會導致UI控制項處於不可預期的狀態。
Handler,MessageQueue,Looper的工作工程如下圖所示:
首先Handler通過post方法將一個Runnable或者send方法將一個消息投遞到handler內部的Looper中,其實post方法最後也是通過send方法來完成的,所以以send方法為例,當send方法被調用後,它會調用MessageQueue中的enqueueMessage方法將這個消息放入MessageQueue中,此時looper發現MessageQueue中存在新消息,會開始處理這個消息,最終Handler中的handleMessage方法就會被調用,因為Looper是運行在創建Handler所在的線程中,這樣一來就完成了消息在子線程和主線程中的傳遞。
MessageQueue主要包含兩個操作,插入(enqueueMessage)和讀取(next),讀取本身會伴隨這刪除操作。enqueueMessage方法的作用是往消息隊列中插入一條消息,next方法的作用是從消息隊列中取出一條消息並將其從消息隊列中移除。
Looper的主要作用就是不斷的從MessageQueue查看是否有新消息,如果沒有就一直阻塞在那裡。
子線程中如果需要使用Handler那就必須先為子線程創建一個Looper,通過Looper.preper()可以為當前線程創建一個 Looper,然後通過Looper.loop()來開啟消息迴圈,當使用完畢後需要調用Looper.quit()來終止消息迴圈,否則由於 Looper內部是一個死迴圈導致子線程會一直處於等待的狀態,也就是線程不能結束。