Android Handler消息機(jī)制詳解

在Android中,只有主線程才能更新UI纵穿,但是主線程不能進(jìn)行耗時(shí)操作,否則會(huì)產(chǎn)生ANR異常奢人,所以常常把耗時(shí)操作放到其他子線程進(jìn)行谓媒。如果在子線程中需要更新UI,一般都是通過(guò)Handler發(fā)送消息何乎,主線接收消息后進(jìn)行相應(yīng)的UI邏輯處理句惯。

一.什么是Handler

   Handler是一個(gè)消息分發(fā)對(duì)象土辩。

   Handler是Android系統(tǒng)提供的一套用來(lái)更新UI的機(jī)制,也是一套消息處理機(jī)制宗弯,可以通過(guò)Handler發(fā)消息脯燃,也可以通過(guò)Handler處理消息。

二.為什么使用Handler

   為了解決多線程并發(fā)的問(wèn)題蒙保!

   比如:如果在一個(gè)activity中有多個(gè)線程同時(shí)更新UI,并且沒(méi)有加鎖欲主,就會(huì)出現(xiàn)界面錯(cuò)亂的問(wèn)題邓厕。但是如果對(duì)這些更新UI的操作都加鎖處理,又會(huì)導(dǎo)致性能下降扁瓢。出于對(duì)性能問(wèn)題的考慮详恼,Android提供這一套使用Handler更新UI的機(jī)制,不用再去關(guān)心多線程的問(wèn)題引几,所有的更新UI的操作昧互,都是在主線程的消息隊(duì)列中去輪詢處理的。

   在Android系統(tǒng)中伟桅,只有主線程才能更新UI敞掘,提到主線程,就不得說(shuō)一下ActivityThread楣铁,一個(gè)應(yīng)用內(nèi)部的邏輯處理都是在ActivityThread內(nèi)部依靠Handler來(lái)進(jìn)行處理的玖雁,比如:activity、service相關(guān)的創(chuàng)建等相關(guān)邏輯盖腕,在應(yīng)用創(chuàng)建后赫冬,會(huì)調(diào)用到ActivityThread內(nèi)部的main()方法,邏輯如下:
public static void main(String[] args) {
    ......
    //創(chuàng)建Looper
    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    //創(chuàng)建Handler
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    //開(kāi)啟loop()循環(huán)
    Looper.loop();
}

  從上面可以看到在ActivityThread里面的main()中溃列,執(zhí)行了Looper.prepareMainLooper()及Looper.loop()劲厌,接下來(lái)一起分析一下Android系統(tǒng)的消息處理機(jī)制。

三.源碼分析

   Android內(nèi)部的消息處理機(jī)制主要是由Handler听隐、Looper补鼻、MessageQueue、Message來(lái)組成的遵绰,具體分工如下:

   _Handler_:負(fù)責(zé)發(fā)送消息及處理消息

   _Looper_:不斷的從消息隊(duì)列中取出消息辽幌,并且將消息給發(fā)送本條消息的Handler

   _MessageQueue_:負(fù)責(zé)存儲(chǔ)消息

   _Message_:消息本身,負(fù)責(zé)攜帶數(shù)據(jù)

1.Looper

   Looper分為主線程和其他子線程椿访,前面講到乌企,主線程的Looper是在進(jìn)程啟動(dòng)后調(diào)用ActivityThread的main()里面通過(guò)prepareMainLooper()創(chuàng)建的:

a.prepareMainLooper()

public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}

   prepareMainLooper()內(nèi)部會(huì)調(diào)用prepare(false)來(lái)進(jìn)行創(chuàng)建,且Looper是不能退出的成玫,然后對(duì)sMainLooper進(jìn)行賦值加酵;

b.prepare()

//只能通過(guò)Looper.prepare()方法去初始化一個(gè)Looper
public static void prepare() {
    prepare(true);
}

//一個(gè)線程中只能有一個(gè)Looper對(duì)象拳喻,否則在第二次嘗試初始化Looper的時(shí)候,就會(huì)拋出異常
private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));//創(chuàng)建了new Looper
}

   子線程通過(guò)prepare()內(nèi)部調(diào)用prepare(true)來(lái)創(chuàng)建對(duì)應(yīng)的Looper猪腕,且Looper是可以退出的冗澈,為什么要退出,后面會(huì)講到陋葡;
public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

private Looper(boolean quitAllowed) {
    //創(chuàng)建Looper的時(shí)候會(huì)創(chuàng)建一個(gè)MessageQueue
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

   Looper構(gòu)造方法內(nèi)會(huì)創(chuàng)建MessageQueue()亚亲,為后續(xù)消息處理做準(zhǔn)備,然后獲取到當(dāng)前的Thread賦值給mThread腐缤,后續(xù)通過(guò)getThread()可以獲取到當(dāng)前的thread捌归,可以用來(lái)判斷是否為主線程。

Android Framework 開(kāi)發(fā)揭秘

第一章 系統(tǒng)啟動(dòng)流程分析

  • 第一節(jié) Android啟動(dòng)概覽
  • 第二節(jié) init.rc解析
  • 第三節(jié) Zygote
  • 第四節(jié) 面試題

第二章 Binder解析

  • 第一節(jié) 宏觀認(rèn)識(shí)Binder
  • 第二節(jié)binder的jni方法注冊(cè)
  • 第三節(jié)binder驅(qū)動(dòng)
  • 第四節(jié) 數(shù)據(jù)結(jié)構(gòu)
  • 第五節(jié) 啟動(dòng)service_manager
  • 第六節(jié)獲取service_manager
  • 第七節(jié) addService流程
  • 第八節(jié) Binder面試題全解析

第三章 Handler解析

  • 第一節(jié) 源碼分析
  • 第二節(jié) 難點(diǎn)問(wèn)題
  • 第三節(jié)Handler常問(wèn)面試題

第四章 AMS 解析

  • 第一節(jié) 引言
  • 第二節(jié) Android架構(gòu)
  • 第三節(jié) 通信方式
  • 第四節(jié) 系統(tǒng)啟動(dòng)系列
  • 第五節(jié) AMS
  • 第六節(jié) AMS 面試題解析

第五章 WMS解析

  • 第一節(jié)Activity與Window相關(guān)概念
  • 第二節(jié) Android窗口管理服務(wù)WindowManagerService計(jì)算Activity窗口大小的過(guò)程分析
  • 第三節(jié)Android窗口管理服務(wù)WindowManagerService對(duì)窗口的組織方式分析
  • 第四節(jié) Android窗口管理服務(wù)WindowManagerService對(duì)輸入法窗口的管理分析
  • 第五節(jié) Android窗口管理服務(wù)WindowManagerService對(duì)壁紙窗口的管理分析
  • ......

第六章PKMS Android10.0 源碼解讀

  • 第一節(jié) 前言 PKMS 是什么東西岭粤?
  • 第二節(jié) PKMS 概述信息
  • 第三節(jié) PKMS角色位置
  • 第四節(jié) PKMS 啟動(dòng)過(guò)程分析
  • 第五節(jié) APK的掃描
  • 第七節(jié) PMS之權(quán)限掃描
  • 第八節(jié) PackageManagerService大綜合筆記

更多的Android可以查看我的個(gè)人介紹O鳌!剃浇!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末巾兆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子虎囚,更是在濱河造成了極大的恐慌角塑,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件溜宽,死亡現(xiàn)場(chǎng)離奇詭異吉拳,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)适揉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)留攒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人嫉嘀,你說(shuō)我怎么就攤上這事炼邀。” “怎么了剪侮?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵拭宁,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我瓣俯,道長(zhǎng)杰标,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任彩匕,我火速辦了婚禮腔剂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘驼仪。我一直安慰自己掸犬,他們只是感情好袜漩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著湾碎,像睡著了一般宙攻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上介褥,一...
    開(kāi)封第一講書(shū)人閱讀 51,763評(píng)論 1 307
  • 那天座掘,我揣著相機(jī)與錄音,去河邊找鬼呻顽。 笑死雹顺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的廊遍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼贩挣,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼喉前!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起王财,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤卵迂,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后绒净,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體见咒,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年挂疆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了改览。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缤言,死狀恐怖宝当,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情胆萧,我是刑警寧澤庆揩,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站跌穗,受9級(jí)特大地震影響订晌,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蚌吸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一锈拨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧套利,春花似錦推励、人聲如沸鹤耍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)稿黄。三九已至,卻和暖如春跌造,著一層夾襖步出監(jiān)牢的瞬間杆怕,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工壳贪, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留陵珍,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓违施,卻偏偏與公主長(zhǎng)得像互纯,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子磕蒲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容