Android的消息機制

從開發(fā)角度來說,Handler是Android消息機制的上層接口,這使得開發(fā)過程中只需要和Handler交互即可。

1.1、Android的消息機制概述

簡單來講,Handler的運行需要底層的MessageQueue和Looper的支撐。MessageQueue是消息隊列,它的內(nèi)部存儲了一組消息,以隊列的的形式對外提供插入和刪除的工作,它的內(nèi)部是采用單鏈表的數(shù)據(jù)結(jié)構(gòu)來存儲消息列表。Looper可以理解為消息循環(huán)。Looper會以無限循環(huán)的形式在MessageQueue中查找是否有新消息,如果有就處理消息,否則一直等待著。Looper中還有一個特殊的概念,那就是ThreadLocal,ThreadLocal并不是線程,它的作用是可以在每個線程中存儲數(shù)據(jù)。

Handler創(chuàng)建的時候會采用當(dāng)前線程的Looper來構(gòu)造消息循環(huán)系統(tǒng),ThreadLocal可以再不同的線程中互不干擾地存儲并提供數(shù)據(jù),通過ThreadLocal可以輕松的獲取每個線程的Looper。

注意,線程默認(rèn)是沒有Looper的,如果需要使用Hnadler就必須為線程創(chuàng)建Looper。我們經(jīng)常提到的主線程也叫UI線程,他就是ActivityThread,ActivityThread被創(chuàng)建時就會初始化Looper,這也是主線程中默認(rèn)可以使用Handler的原因。

Android無法在子線程中更新UI,因為Android的UI控件不是線程安全的。

注意,Looper是運行在創(chuàng)建Handler所在的線程中的,這樣一來Handler中的業(yè)務(wù)邏輯就會被切換到創(chuàng)建Handler所在的線程中去執(zhí)行了。

1.2、Android的消息機制分析

1.2.1、ThreadLocal的工作原理

ThreadLocal是一個線程內(nèi)部的數(shù)據(jù)存儲類,通過它可以在指定的線程中存儲數(shù)據(jù)。只有在指定的線程中可以獲取到數(shù)據(jù)。

不同的線程創(chuàng)建了不同的Values,Values下有不同的數(shù)組table,所以不同的線程存儲的數(shù)據(jù)不同。

1.2.2、MessageQueue的工作原理

MessageQueue包含兩個操作:插入和讀取。讀取操作本身伴隨著刪除操作,插入和讀取對應(yīng)的方法分別是enqueueMessage(插入一條消息到消息隊列)和next(取出一條消息并將其從消息隊列中移除)。

1.2.3、Looper的工作原理

private Looper(boolean quitAllowed){

????????? mQueue = newMessageQueue(quitAllowed) ;

????????? mThread = Thread.currentThread() ;

}

從構(gòu)造方法可以看出,Looper會創(chuàng)建一個MessageQueue,然后將當(dāng)前線程對象保存。

Handler的工作需要Looper,沒有Looper的線程就會報錯。創(chuàng)建Looper:

Looper.prepare()即可為當(dāng)前線程創(chuàng)建一個Looper,接著通過Looper.loop()來開啟消息循環(huán)。

Looper提供了quit(直接退出)和quitSafely(消息隊列里的消息執(zhí)行完畢才退出)來退出一個Looper。

子線程中如手動創(chuàng)建了Looper,所有事情處理完后應(yīng)該調(diào)用quit,否則子線程一直等待狀態(tài)。

當(dāng)Looper方法是一個死循環(huán),唯一跳出循環(huán)的方式是MessageQueue的next方法反回了nul。當(dāng)Looper的quit方法調(diào)用時,Looper就會調(diào)用MessageQueue的quit或者quitSafely方法來通知消息隊列退出,當(dāng)消息隊列標(biāo)記為退出狀態(tài)是,它的next方法就會返回null。

所以說Looper必須退出,否則loop就會一直循環(huán)下去。當(dāng)loop方法去調(diào)用MessageQueue的next方法來獲取新消息,而next是一個阻塞操作,當(dāng)沒有消息時,next方法會一直阻塞,導(dǎo)致loop方法一直阻塞在那里。有消息looper處理:msg.target.dispatchMessage(msg) ;msg.target是發(fā)送這條消息的Handler對象

1.2.4、Handler的工作原理

Handler的工作包括消息的發(fā)送和接收過程。發(fā)送可用post系列方法和send系列方法。(post最終通過send)。

Handler發(fā)送消息的過程僅僅是向消息隊列中插入了一條消息,MessageQueue的next方法就會返回這條消息給Looper,Looper收到消息后就開始處理消息,最終消息由Looper交給Handler處理,即handler的dispatchMesage方法被調(diào)用

Handler處理消息的三個方式對應(yīng)dispatchMesage方法的三個處理情況 :

1)handler.post(Runnable r)

2) handler = new Handler(callback)

3) 派生子類,重寫handleMessage方法。

Handler還有一個特殊的構(gòu)造方法,那就是通過特定的Looper來構(gòu)造Handler

public?? Handler (Looper looper){

?????????? this(looper,null,false) ;

}

可以實現(xiàn)一些特殊的功能。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言: 提到Android消息機制大家應(yīng)該都不陌生,在日常開發(fā)中都不可避免地要涉及到這方面的內(nèi)容。從開發(fā)的角度來說...
    JiaYang627閱讀 404評論 0 1
  • 前言 Handler是Android消息機制的上層接口,平時使用起來很方便,我們可以通過它把一個任務(wù)切換到Hand...
    eagleRock閱讀 1,766評論 0 13
  • 1. ANR異常 Application No Response:應(yīng)用程序無響應(yīng)。在主線程中,是不允許執(zhí)行耗時的操...
    JackChen1024閱讀 1,611評論 0 3
  • 學(xué)習(xí)內(nèi)容 Android 的消息機制 Handler 即其底層支撐 原文開篇部分: 從開發(fā)角度來說,Handler...
    whd_Alive閱讀 386評論 0 0
  • 今天莫名的發(fā)燒生病了,渾身疼的沒法正常呼吸,眼冒金星,試著咽了咽口水都很痛苦,艱難的邁著沉重的雙腿去洗了手,然后去...
    aminaxiu閱讀 320評論 0 0

友情鏈接更多精彩內(nèi)容