Android Handler消息機制原理
①是什么?
Handler是Android SDK中處理異步類消息的核心類腰根,其作用是讓子線程通過與UI通信來更新UI界面?
總結(jié)起來也可以這樣說:?
1.當應(yīng)用程序啟動時或南,會初始化一個UI線程?
2.UI線程中創(chuàng)建了Looper,所以是一個循環(huán)工作線程?
3.創(chuàng)建Looper時,Looper會創(chuàng)建一個MessageQueue?
4.UI中的Looper會不斷從MessageQueue中取出消息
②什么是Looper敬飒?什么是MessageQueue痕鳍?
1)Looper: 一個線程可以產(chǎn)生一個Looper對象硫豆,由它來管理此線程里的MessageQueue(消息隊列)。
2)Handler: 你可以構(gòu)造Handler對象來與Looper溝通笼呆,以便push新消息到MessageQueue里;或者接收Looper從Message Queue取出)所送來的消息熊响。
3) Message Queue(消息隊列):用來存放線程放入的消息。
4)線程:UIthread 通常就是main thread诗赌,而Android啟動程序時會替它建立一個MessageQueue汗茄。
③做什么?
(1).在新啟動的線程中發(fā)送消息
(2).在主線程中獲取铭若,處理消息洪碳。
解釋:(1)?當應(yīng)用程序啟動時,Android首先會開啟一個主線程 (也就是UI線程) 叼屠, 主線程為管理界面中的UI控件瞳腌, 進行事件分發(fā), 比如說镜雨, 你要是點擊一個 Button 嫂侍,Android會分發(fā)事件到Button上,來響應(yīng)你的操作。?主線程(UI線程)就是android程序從啟動運行到最后的程序挑宠。
(2)?如果此時需要一個耗時的操作菲盾,例如: 聯(lián)網(wǎng)讀取數(shù)據(jù),或者讀取本地較大的一個文件的時候痹栖,你不能把這些操作放在主線程中亿汞,如果你放在主線程中的話,界面會出現(xiàn)假死現(xiàn)象揪阿, 如果5秒鐘還沒有完成的話疗我,會收到Android系統(tǒng)的一個錯誤提示? "強制關(guān)閉"。
(3)這個時候我們需要把這些耗時的操作南捂,放在一個子線程中吴裤,因為子線程涉及到UI更新,Android主線程是線程不安全的溺健, 也就是說麦牺,更新UI只能在主線程中更新,子線程中操作是危險的鞭缭。
(4)這個時候剖膳,Handler就出現(xiàn)了。岭辣,來解決這個復(fù)雜的問題 吱晒,由于Handler運行在主線程中(UI線程中),? 它與子線程可以通過Message對象來傳遞數(shù)據(jù)沦童, 這個時候仑濒,Handler就承擔著接受子線程傳過來的(子線程用sendMessage()方法傳弟)Message對象(里面包含數(shù)據(jù))? , 把這些消息放入主線程隊列中偷遗,配合主線程進行更新UI墩瞳。
④怎么用?
handler可以分發(fā)Message對象和Runnable對象到主線程中氏豌,每個Handler實例喉酌,都會綁定到創(chuàng)建他的線程中(一般是位于主程),它有兩個作用:
? ??????????(1)合理調(diào)度安排消息和runnable對象泵喘,使它們在將來的某個點被執(zhí)行.
? ??????????(2)安排一個動作在不同的線程中執(zhí)行
Handler中開啟線程和分發(fā)消息的一些方法:
?post(Runnable)直接開啟Runnable線程
?postAtTime(Runnable泪电,long)在指定的時間long,開始啟動線程
?postDelayed(Runnable long)在延遲long時間后涣旨,啟動Runnable線程
?sendEmptyMessage(int)?發(fā)送指定的消息歪架,通過參數(shù)int來區(qū)分不同的消息
?sendMessage(Message)發(fā)送消息到UI線程中
?sendMessageAtTime(Message,long)???? 這個long代表的是系統(tǒng)時間霹陡,不推薦用
?sendMessageDelayed(Message和蚪,long)??? 此方法long代表調(diào)用后幾秒后執(zhí)行止状。
?sendMessage類方法, 允許你安排一個帶數(shù)據(jù)的Message對象到隊列中攒霹,等待更新.
handler基本使用:1)在主線程中怯疤,使用handler很簡單,new一個Handler對象實現(xiàn)其handleMessage方法催束,在?handleMessage?中提供收到消息后相應(yīng)的處理方法即可集峦。(接收消息,并且更新UI)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2)在新啟動的線程中發(fā)送消息
⑤handler機制的原理
1.Handler創(chuàng)建消息
? ?? ???每一個消息都需要被指定的Handler處理抠刺,通過Handler創(chuàng)建消息便可以完成此功能塔淤。Android消息機制中引入了消息池。Handler創(chuàng)建消息時首先查詢消息池中是否有消息存在速妖,如果有直接從消息池中取得高蜂,如果沒有則重新初始化一個消息實例。使用消息池的好處是:消息不被使用時罕容,并不作為垃圾回收备恤,而是放入消息池,可供下次Handler創(chuàng)建消息時使用锦秒。消息池提高了消息對象的復(fù)用露泊,減少系統(tǒng)垃圾回收的次數(shù)。消息的創(chuàng)建流程如圖所示旅择。
2.Handler發(fā)送消息
UI主線程初始化第一個Handler時會通過ThreadLocal創(chuàng)建一個Looper惭笑,該Looper與UI主線程一一對應(yīng)。使用ThreadLocal的目的是保證每一個線程只創(chuàng)建唯一一個Looper砌左。之后其他Handler初始化的時候直接獲取第一個Handler創(chuàng)建的Looper脖咐。Looper初始化的時候會創(chuàng)建一個消息隊列MessageQueue铺敌。至此汇歹,主線程、消息循環(huán)偿凭、消息隊列之間的關(guān)系是1:1:1产弹。
Handler、Looper弯囊、MessageQueue的初始化流程如圖所示:
Hander持有對UI主線程消息隊列MessageQueue和消息循環(huán)Looper的引用痰哨,子線程可以通過Handler將消息發(fā)送到UI線程的消息隊列MessageQueue中。
3.Handler處理消息
UI主線程通過Looper循環(huán)查詢消息隊列UI_MQ匾嘱,當發(fā)現(xiàn)有消息存在時會將消息從消息隊列中取出斤斧。首先分析消息,通過消息的參數(shù)判斷該消息對應(yīng)的Handler霎烙,然后將消息分發(fā)到指定的Handler進行處理撬讽。