Handler原理

1.handler基本信息:

定義:一套 Android 消息傳遞機(jī)制。

作用:在多線程的應(yīng)用場(chǎng)景中,將工作線程中需更新UI的操作信息 傳遞到 UI主線程,從而實(shí)現(xiàn) 工作線程對(duì)UI的更新處理捉偏,最終實(shí)現(xiàn)異步消息的處理。

使用Handler的原因:將工作線程需操作UI的消息 傳遞到主線程呻疹,使得主線程可根據(jù)工作線程的需求 更新UI适贸,從而避免線程操作不安全的問(wèn)題戈钢。

消息(Message):

定義:線程間通訊的數(shù)據(jù)單元(即Handler接收&處理的消息對(duì)象)

作用:存儲(chǔ)需操作的通信信息

消息隊(duì)列(Message Queue):

定義:一種數(shù)據(jù)結(jié)構(gòu)(存儲(chǔ)特點(diǎn):先進(jìn)先出)

作用:存儲(chǔ)Handler發(fā)送過(guò)來(lái)的消息(Message)

處理者(handler):

定義:主線程與子線程的通信媒介 線程消息的主要處理者

作用:添加消息(Message)到消息隊(duì)列(message Queue)處理循環(huán)器(Looper)分派過(guò)來(lái)的消息(message)

循環(huán)器(Looper):

定義:消息隊(duì)列(Message Queue)與處理者(Handler)的通信媒介

作用:消息循環(huán),即消息獲取:循環(huán)取出消息隊(duì)列(Message Queue)的消息(message)消息分發(fā):將取出的消息(Message)發(fā)送給對(duì)應(yīng)的處理者(Handler)

2..Handler使用方式 因發(fā)送消息到消息隊(duì)列的方式不同而不同

共分為2種:使用Handler.sendMessage()惊奇、使用Handler.post()

2原理


通過(guò)handler.sendMessage這個(gè)方法互躬,把當(dāng)前的消息對(duì)象message傳入到handler中,通過(guò)handler中的messagequeue對(duì)象的引用(通過(guò)在handler的構(gòu)造函數(shù)中颂郎,用looper獲取到的)吼渡,把Message放入到MessageQueue中。在message存放的時(shí)候乓序,message對(duì)象的target屬性記錄了當(dāng)前的handler寺酪。message通過(guò)消息的執(zhí)行時(shí)間when,從小到大排列插入到消息鏈表中替劈。我們looper的loop方法中的for(死循環(huán))去查看當(dāng)前的MessageQueue鏈表中是否有需要執(zhí)行的Message寄雀。通過(guò)Message的when(消息的執(zhí)行時(shí)間判斷)和當(dāng)前的系統(tǒng)時(shí)間戳做對(duì)比,如果當(dāng)前的系統(tǒng)時(shí)間戳小于當(dāng)前messagequeue鏈表中的消息執(zhí)行時(shí)間陨献,當(dāng)前的執(zhí)行進(jìn)入等待狀態(tài)盒犹。(管道機(jī)制,nativepollonce)如果當(dāng)前的系統(tǒng)時(shí)間戳大于或等于當(dāng)前的MessageQueue鏈表中的消息執(zhí)行時(shí)間眨业,我們就把當(dāng)前的message從消息鏈表中刪除急膀,并且把該消息返回給Looper的loop方法中。在loop方法中獲取到message以后判斷message所對(duì)應(yīng)的target(也就是發(fā)送message的handler)是否存在坛猪,如果存在就調(diào)用target.dispathMessage方法把當(dāng)前的message

傳入脖阵,在dispathMessage方法中皂股,我們將調(diào)用handleMessage這個(gè)方法墅茉。把當(dāng)前取出的message傳出去。這樣在我們handler中重寫(xiě)的handleMessage就拿到了當(dāng)前處理的消息呜呐。

4.Handler機(jī)制的工作流程主要包括4個(gè)步驟:

(1).異步通信準(zhǔn)備:

具體描述:在主線程中創(chuàng)建:處理器對(duì)象(Looper)消息隊(duì)列 對(duì)象(Message Queue)Handler 對(duì)象

(2).消息發(fā)送

具體描述:工作線程通過(guò)Handler發(fā)送消息(Message)到消息隊(duì)列(Message Queue)中

(3).消息循環(huán)

具體描述:消息出隊(duì):Looper循環(huán)取出消息隊(duì)列(Message Queue)中的消息(Message)消息分發(fā):Looper將取出的消息(Message)發(fā)送給創(chuàng)建消息的處理著(Handler)

(4).消息處理

具體描述:處理者(Handler)接收處理器(Looper)發(fā)送過(guò)來(lái)的消息(Message)處理者(Handler)根據(jù)消息(Message)進(jìn)行UI操作

5.當(dāng)創(chuàng)建Handler對(duì)象時(shí)就斤,則通過(guò) 構(gòu)造方法 自動(dòng)關(guān)聯(lián)當(dāng)前線程的Looper對(duì)象 & 對(duì)應(yīng)的消息隊(duì)列對(duì)象(MessageQueue),從而 自動(dòng)綁定了 實(shí)現(xiàn)創(chuàng)建Handler對(duì)象操作的線程

創(chuàng)建主線程時(shí)蘑辑,會(huì)自動(dòng)調(diào)用ActivityThread的1個(gè)靜態(tài)的main()洋机;而main()內(nèi)則會(huì)調(diào)用Looper.prepareMainLooper()為主線程生成1個(gè)Looper對(duì)象,同時(shí)也會(huì)生成其對(duì)應(yīng)的MessageQueue對(duì)象

即 主線程的Looper對(duì)象自動(dòng)生成洋魂,不需手動(dòng)生成绷旗;而子線程的Looper對(duì)象則需手動(dòng)通過(guò)Looper.prepare()創(chuàng)建

6.在子線程若不手動(dòng)創(chuàng)建Looper對(duì)象 則無(wú)法生成Handler對(duì)象

根據(jù)Handler的作用(在主線程更新UI),故Handler實(shí)例的創(chuàng)建場(chǎng)景 主要在主線程

消息循環(huán)的操作 = 消息出隊(duì) + 分發(fā)給對(duì)應(yīng)的Handler實(shí)例

分發(fā)給對(duì)應(yīng)的Handler的過(guò)程:根據(jù)出隊(duì)消息的歸屬者通過(guò)dispatchMessage(msg)進(jìn)行分發(fā)副砍,最終回調(diào)復(fù)寫(xiě)的handleMessage(Message msg)衔肢,從而實(shí)現(xiàn) 消息處理 的操作

特別注意:在進(jìn)行消息分發(fā)時(shí)(dispatchMessage(msg)),會(huì)進(jìn)行1次發(fā)送方式的判斷:

若msg.callback屬性不為空豁翎,則代表使用了post(Runnable r)發(fā)送消息角骤,則直接回調(diào)Runnable對(duì)象里復(fù)寫(xiě)的run()

若msg.callback屬性為空,則代表使用了sendMessage(Message msg)發(fā)送消息心剥,則回調(diào)復(fù)寫(xiě)的handleMessage(msg)

7.線程安全就是多線程訪問(wèn)時(shí)邦尊,采用了加鎖機(jī)制背桐,當(dāng)一個(gè)線程訪問(wèn)該類(lèi)的某個(gè)數(shù)據(jù)時(shí),進(jìn)行保護(hù)蝉揍,其他線程不能進(jìn)行訪問(wèn)直到該線程讀取完链峭,其他線程才可使用。不會(huì)出現(xiàn)數(shù)據(jù)不一致或者數(shù)據(jù)污染疑苫。 線程不安全就是不提供數(shù)據(jù)訪問(wèn)保護(hù)熏版,有可能出現(xiàn)多個(gè)線程先后更改數(shù)據(jù)造成所得到的數(shù)據(jù)是臟數(shù)據(jù)。

8.ThreadLocal提供了線程內(nèi)存儲(chǔ)變量的能力捍掺,這些變量不同之處在于每一個(gè)線程讀取的變量是對(duì)應(yīng)的互相獨(dú)立的撼短。通過(guò)get和set方法就可以得到當(dāng)前線程對(duì)應(yīng)的值。

ThreadLocal的靜態(tài)內(nèi)部類(lèi)ThreadLocalMap為每個(gè)Thread都維護(hù)了一個(gè)數(shù)組table挺勿,ThreadLocal確定了一個(gè)數(shù)組下標(biāo)曲横,而這個(gè)下標(biāo)就是value存儲(chǔ)的對(duì)應(yīng)位置。不瓶。

ThreadLocal是解決線程安全問(wèn)題一個(gè)很好的思路禾嫉,它通過(guò)為每個(gè)線程提供一個(gè)獨(dú)立的變量副本解決了變量并發(fā)訪問(wèn)的沖突問(wèn)題。在很多情況下蚊丐,ThreadLocal比直接使用synchronized同步機(jī)制解決線程安全問(wèn)題更簡(jiǎn)單熙参,更方便,且結(jié)果程序擁有更高的并發(fā)性麦备。

在每個(gè)線程Thread內(nèi)部有一個(gè)ThreadLocal.ThreadLocalMap類(lèi)型的成員變量threadLocals孽椰,這個(gè)threadLocals就是用來(lái)存儲(chǔ)實(shí)際的變量副本的,鍵值為當(dāng)前ThreadLocal變量凛篙,value為變量副本(即T類(lèi)型的變量)黍匾。 初始時(shí),在Thread里面呛梆,threadLocals為空锐涯,當(dāng)通過(guò)ThreadLocal變量調(diào)用get()方法或者set()方法,就會(huì)對(duì)Thread類(lèi)中的threadLocals進(jìn)行初始化填物,并且以當(dāng)前ThreadLocal變量為鍵值纹腌,以ThreadLocal要保存的副本變量為value,存到threadLocals滞磺。 然后在當(dāng)前線程里面升薯,如果要使用副本變量,就可以通過(guò)get方法在threadLocals里面查找雁刷。

實(shí)際的通過(guò)ThreadLocal創(chuàng)建的副本是存儲(chǔ)在每個(gè)線程自己的threadLocals中的覆劈;

為何threadLocals的類(lèi)型ThreadLocalMap的鍵值為T(mén)hreadLocal對(duì)象,因?yàn)槊總€(gè)線程中可有多個(gè)threadLocal變量,就像上面代碼中的longLocal和stringLocal责语;

在進(jìn)行g(shù)et之前炮障,必須先set,否則會(huì)報(bào)空指針異常坤候;如果想在get之前不需要調(diào)用set就能正常訪問(wèn)的話胁赢,必須重寫(xiě)initialValue()方法。 因?yàn)樵谏厦娴拇a分析過(guò)程中白筹,我們發(fā)現(xiàn)如果沒(méi)有先set的話智末,即在map中查找不到對(duì)應(yīng)的存儲(chǔ),則會(huì)通過(guò)調(diào)用setInitialValue方法返回i徒河,而在setInitialValue方法中系馆,有一個(gè)語(yǔ)句是T value = initialValue(), 而默認(rèn)情況下顽照,initialValue方法返回的是null由蘑。

9.handler.post和handler.sendMessage本質(zhì)上是沒(méi)有區(qū)別的,都是發(fā)送一個(gè)消息到消息隊(duì)列中代兵,而且消息隊(duì)列和handler都是依賴(lài)于同一個(gè)線程的尼酿。

send方案發(fā)送消息(需要回調(diào)才能接收消息)

1、sendMessage(Message) 立即發(fā)送Message到消息隊(duì)列

2植影、sendMessageAtFrontOfQueue(Message) 立即發(fā)送Message到隊(duì)列裳擎,而且是放在隊(duì)列的最前面

3、sendMessageAtTime(Message,long) 設(shè)置時(shí)間思币,發(fā)送Message到隊(duì)列

4鹿响、sendMessageDelayed(Message,long) 延時(shí)若干毫秒后,發(fā)送Message到隊(duì)列

post方案 立即發(fā)送Message到消息隊(duì)列

1支救、post(Runnable) 立即發(fā)送Message到消息隊(duì)列

2抢野、postAtFrontOfQueue(Runnable) 立即發(fā)送Message到隊(duì)列拷淘,而且是放在隊(duì)列的最前面

3各墨、postAtTime(Runnable,long) 設(shè)置時(shí)間,發(fā)送Message到隊(duì)列

4启涯、postDelayed(Runnable,long) 在延時(shí)若干毫秒后贬堵,發(fā)送Message到隊(duì)列

10.handler機(jī)制中包含4個(gè)關(guān)鍵類(lèi)(下面對(duì)源碼的解析也是從這4個(gè)類(lèi)入手),Message(消息)结洼,MessageQueue(消息隊(duì)列)黎做,Looper(輪詢器),Handler(消息發(fā)送和接收并處理)松忍,簡(jiǎn)單一句話概括就是:handler負(fù)責(zé)發(fā)送message蒸殿,將其加入到MessageQueue中,Looper不間斷的從MessageQueue中取出消息,并發(fā)送給對(duì)應(yīng)的handler實(shí)例去處理.

11.主線程與子線程

主線程((Ui線程宏所,Main.thread):

定義:當(dāng)應(yīng)用程序第一次啟動(dòng)時(shí)酥艳,會(huì)同時(shí)開(kāi)啟1條主線程。

作用:處理與UI相關(guān)的事件(如更新操作等)爬骤。

子線程(工作線程):

定義:人為手動(dòng)開(kāi)啟的線程充石。

作用:執(zhí)行耗時(shí)操作(如網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)加載等)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末霞玄,一起剝皮案震驚了整個(gè)濱河市骤铃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坷剧,老刑警劉巖惰爬,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異惫企,居然都是意外死亡补鼻,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)雅任,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)风范,“玉大人,你說(shuō)我怎么就攤上這事沪么∨鹦觯” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵禽车,是天一觀的道長(zhǎng)寇漫。 經(jīng)常有香客問(wèn)我,道長(zhǎng)殉摔,這世上最難降的妖魔是什么州胳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮逸月,結(jié)果婚禮上栓撞,老公的妹妹穿的比我還像新娘。我一直安慰自己碗硬,他們只是感情好瓤湘,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著恩尾,像睡著了一般弛说。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上翰意,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天木人,我揣著相機(jī)與錄音信柿,去河邊找鬼。 笑死醒第,一個(gè)胖子當(dāng)著我的面吹牛角塑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播淘讥,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼圃伶,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蒲列?” 一聲冷哼從身側(cè)響起窒朋,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蝗岖,沒(méi)想到半個(gè)月后侥猩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡抵赢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年欺劳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铅鲤。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡划提,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出邢享,到底是詐尸還是另有隱情鹏往,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布骇塘,位于F島的核電站伊履,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏款违。R本人自食惡果不足惜唐瀑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望插爹。 院中可真熱鬧哄辣,春花似錦、人聲如沸递惋。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)萍虽。三九已至,卻和暖如春形真,著一層夾襖步出監(jiān)牢的瞬間杉编,已是汗流浹背超全。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留邓馒,地道東北人嘶朱。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像光酣,于是被迫代替她去往敵國(guó)和親疏遏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359