Android開發中的Handler機制及使用場景

介紹:

Handler機制指的是Android的消息機制,它的使用很簡單,通過它可以輕松的將一個任務切換到Handler所在的線程去執行,我們用的最多的地方也就是Handler刷新UI的功能,其實,它還有很多用途,比如子線程中進行消耗的I/O操作,讀取文件等,而我們用它來刷新UI,是因為子線程無法刷新UI,可以通過它來切換回主線程執行,因此,本質來說,它只是常用來刷新UI而已

Handler機制

Handler機制也就是消息機制,它與MessageQueue和Looper完成一個體系.

MessageQueue

從字面意思我們不難知道,它是個消息隊列,也就是說,它存儲了所有的消息,也可以叫它消息列表,我們從Handler的sendMessage發出的消息都會被存儲到這里面

Looper

Looper翻譯成中文就是循環,意思就是消息循環,它會無限循環的從MessageQueue中讀取消息,如果有則處理,沒有就一直等待,MessageQueue雖然是消息隊列,然而它并沒有能對消息進行處理的操作,因此,需要Looper的支持

Handler

Handler主要負責發送消息到MessageQueue,它在創建的時候,會采用當前線程的Looper來構成消息系統,但是注意了,線程默認是沒有Looper的,而使用Handler就一定需要有Looper才可以執行,主線程之所以能使用Handler,那是因為主線程是ActivityThread,ActivityThread被創建的時候會初始化Looper,所以它能使用Handler,所以主線程也叫UI線程

所以,我們大概就知道了Handler是怎么工作的了,Handler創建完之后,通過Handler的send方法將一個消息存儲到MessageQueue中,然后Looper循環從MessageQueue中讀取消息并且處理,處理完之后如果還有消息就繼續處理,否則就等待

上面就是Handler和MessageQueue,Looper的關系,這三者其實是一個整體,我們來思考下幾個問題,①:為什么不能再子線程中更新UI,②:為什么需要用Handler來刷新UI,③:如果非要在子線程中更新UI怎么辦,現在我們來說說這幾個問題

問題一:

之所以Android不允許在子線程中更新UI,那是因為,子線程是可以無限被創建的,我們假想下,如果有5條子線程,每條子線程都有一個UI控件,我們去刷新UI的時候會出現什么后果,后果就是我們達不到預期的UI控件刷新順序,我們可能想控件1先刷新控件2再刷新,有可能就會出現相反的順序,也可能同時刷新,并且,如果有N條子線程,線程并發問題會更嚴重,所以Android必須要在UI線程中更新UI,也有可能會問,為什么不對UI控件上鎖呢?原因有兩個:1,上鎖會讓UI訪問邏輯復雜化,不靈活,如果我需要在其他線程訪問UI的話,比較難處理? 2,加鎖會阻塞線程的執行,所以,這就是為什么我們需要在UI線程中更新UI的原因

問題二:

我們知道,在異步線程中訪問網絡請求之后,需要刷新UI的時候是不能再子線程中執行的,Handler可以做到刷新UI,那是因為Handler在創建的時候會調用當前線程的Looper對象,Looper對象是對消息的處理,所以,我們執行完請求之后,可以切換回主線程,調用主線程的Looper對象去刷新UI,這里要注意了,因為Handler會調用當前線程的Looper對象,所以Handler需要在主線程中創建,否則會報錯的,所以總的來說,Handler更像一個切換線程的類

問題三:

如果我們非要在子線程中去刷新UI,也不是沒有辦法,我們可以創建一個Looper,然后去獲取主線程的Looper對象即可,又或者可以在一個有Looper的線程中創建Handler也可以,但是這樣就毫無意義了,所以總的來說,當我們需要使用Handler的時候,就在UI線程中去創建,我們來看看怎么獲取主線程的Looper對象和創建Looper對象

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容