Handler+Messageu原理分析02

Handler流程分析

210329210803.png

在APP啟動(dòng)的時(shí)候,就已經(jīng)創(chuàng)建了主線程的Looper對(duì)象镰惦,在ActivityThread中的main方法中進(jìn)行創(chuàng)建犬绒。在sendMessage()的時(shí)候都會(huì)調(diào)用enqueueMessage()壓入消息到消息隊(duì)列里面,主要操作就是將send的message賦值給了一個(gè)全局的message(源碼中變量名為MMessage)。在消息隊(duì)列當(dāng)中取消息的時(shí)候有個(gè)Looper.loop()方法一直在輪尋消息礼华,按照先進(jìn)先出的原則取消息拗秘,調(diào)用了queue.next方法,該方法就是將message進(jìn)行返回聘殖,在next方法中就是將之前賦值的全局變量的mMessage再返回回來,之后調(diào)用handler里面的dispatchMessage()方法實(shí)現(xiàn)了線程切換(如果在子線程中發(fā)送了消息)而該方法調(diào)用了handlerMessage()并由實(shí)例化handler的時(shí)候重寫該方法取到消息奸腺。

提到了Handler大家都會(huì)聯(lián)想到另外三個(gè)對(duì)象,與Handler息息相關(guān)帮非。如圖所示
0329211822.png

在UI線程當(dāng)中使用Handler

210329212221.png

在子線程中使用Handler

0210329212350.png

注意紅框里面的代碼,為什么要在子線程中寫這兩句話呢座慰。我們知道項(xiàng)目啟動(dòng)會(huì)直接調(diào)用主線程中main方法去實(shí)例化looper對(duì)象并通過Looper.looper()激活消息并獲取消息的一系列流程版仔,而在子線程當(dāng)中如果我們直接new Handler(),根據(jù)threadLocalMap取looper的時(shí)候肯定是為null的蛮粮,報(bào)空指針,原因就是沒有對(duì)Looper進(jìn)行初始化然想,所以調(diào)用Looper.prepare()方法進(jìn)行new Looper()

來看下張圖

20210329213003.png

很清楚我們可以看到無論你調(diào)用post sendMessage sendEmptyMessage 等等 最終都會(huì)調(diào)用 enqueueMessage()將消息壓入消息隊(duì)列當(dāng)中令哟。

Handler整個(gè)流程圖

handler.png

Handler的post方法為什么是主線程

我們?cè)趯憄ost方法的時(shí)候會(huì)new一個(gè)runnable励饵,而該runerable會(huì)被封裝成一個(gè)message對(duì)象進(jìn)行發(fā)送消息。源碼顯示如下

private static Message getPostMessage(Runnable r){
   Message m = Message.obtain();
   m.callback = r;
   return m;
}

大家來看這里面message的callback被賦值了該Runnable颓鲜,注意不是Handler實(shí)例化的時(shí)候new 的callback。這樣就通過 sendMessageDelayed(getPostMessage(r),0)方法進(jìn)行將消息發(fā)送瘤袖,調(diào)用了dispatchMessage(Message msge)進(jìn)行了線程的切換昂验,該方法源碼如下

 public void dispatchMessage(Message msg){
   if(msg.callback!=null){
     handleCallback(msg);
   }else{
     if(mCallbackz!=null){
       if{mCallback.handleMessage(msg);
         return;
       }
       handleMessage(msge);
     }
   }
 }
private static void handleCallback(Message message){
  message.callback.run()
}

所以最終就會(huì)在主線程中執(zhí)行post方法中實(shí)現(xiàn)的run方法

小結(jié)

1.為什么主線程用Looper死循環(huán)不會(huì)引發(fā)ANR異常
 因?yàn)樵贚ooper.next()開啟死循環(huán)的時(shí)候既琴,一旦需要等待時(shí)或者還沒有執(zhí)行到的時(shí)候,會(huì)調(diào)用NDK里面的JNI方法逆济,
 釋放當(dāng)前時(shí)間片磺箕,這樣就不會(huì)造成ANR異常了
2.為什么Handler構(gòu)造方法里面Looper不是直接new的
如果在Handler構(gòu)造方法中new Looper松靡,怕是無法保證Looper的唯一性了,只有用Looper.prepare()才能保證唯一性雕欺,
具體看prepare方法
MessageQueue為什么要放在Looper的私有構(gòu)造方法里面初始化
因?yàn)橐粋€(gè)線程只能綁定一個(gè)Looper,所以在Looper構(gòu)造方法里面初始化可以保證mQueue也是唯一的
Thread對(duì)應(yīng)一個(gè)Looper對(duì)應(yīng)一個(gè)mQueue
主線程里面的Looper.prepare/Looper.loop,是一直在無限循環(huán)里面的嗎蛛枚?
 是的

感謝

感謝大家的閱讀 點(diǎn)個(gè)贊唄
關(guān)注我 持續(xù)更新

Github

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末脸哀,一起剝皮案震驚了整個(gè)濱河市撞蜂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌溉贿,老刑警劉巖宇色,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件例隆,死亡現(xiàn)場(chǎng)離奇詭異抢蚀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)唱逢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門坞古,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人博投,你說我怎么就攤上這事绸贡。” “怎么了毅哗?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵听怕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我虑绵,道長(zhǎng)尿瞭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任翅睛,我火速辦了婚禮声搁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捕发。我一直安慰自己疏旨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著窃植,像睡著了一般葛超。 火紅的嫁衣襯著肌膚如雪巩掺。 梳的紋絲不亂的頭發(fā)上豫缨,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼敬拓。 笑死厕诡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的寿羞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼量瓜,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼扔傅!你這毒婦竟也來了试读?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎纽匙,沒想到半個(gè)月后烛缔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寸宵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片七扰。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡立由,死狀恐怖锐膜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情牺堰,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布常拓,位于F島的核電站,受9級(jí)特大地震影響掂恕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜店枣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一钧唐、第九天 我趴在偏房一處隱蔽的房頂上張望缀棍。 院中可真熱鬧爬范,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至丢氢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間载碌,已是汗流浹背弦撩。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工点晴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屠橄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓夺脾,卻偏偏與公主長(zhǎng)得像馒疹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

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