Handler是做什么的?
Handler了它在安卓中常見的工作就是子線程與主線程的通信留美,其實(shí)可以直接歸類為線程和線程間的通信
Handler工作原理是什么?
談到Handler會(huì)涉及到以下幾個(gè)類
Handler伸刃、Message谎砾、Looper、MessageQueue
我們一個(gè)一個(gè)來說捧颅,首先設(shè)置場(chǎng)景在一個(gè)線程中通知另一個(gè)線程
首先我們需要?jiǎng)?chuàng)建一個(gè)Looper它用于去輪詢MessageQueue景图,如果MessageQueue里面有Message,那么使用Handler去處理Message
1碉哑,創(chuàng)建Looper和創(chuàng)建MessageQueue
首先在一個(gè)線程里要用Handler挚币,那么需要準(zhǔn)備Looper亮蒋,調(diào)用Looper.prepare(),我們?cè)谥骶€程里面不用準(zhǔn)備Looper妆毕,那么是因?yàn)樵谖覀兊闹骶€程中已經(jīng)給我們初始化好了Looper慎玖,
在準(zhǔn)備Looper的時(shí)候會(huì)去校驗(yàn)這個(gè)線程中是否存在Looper,如果有Looper那么拋出異常(注意:有一些面試官會(huì)問如何判斷一個(gè)線程中是否存在一個(gè)Looper的笛粘,它用的是ThreadLocal凄吏,它的作用是在線程范圍內(nèi)保證變量的唯一性,Thread中會(huì)維護(hù)一個(gè)類似HashMap的東西闰蛔,然后用ThreadLocal對(duì)象作為key,value就是要存儲(chǔ)的變量值图柏,這樣就保證了存儲(chǔ)數(shù)據(jù)的唯一性)
如果沒有Looper那么new一個(gè)Looper序六,new Looper的同時(shí)會(huì)new 一個(gè)MessageQueue(注意:一個(gè)線程中只有一個(gè)Looper一個(gè)MessageQueue)
然后Looper.loop()就可以啟動(dòng)輪訓(xùn)來輪訓(xùn)消息隊(duì)列了
2,創(chuàng)建Handler
這個(gè)我們?cè)谑煜げ贿^了蚤吹,繼承一個(gè)Handler然后復(fù)寫handlerMessage方法例诀,這里其實(shí)面試官也可以問一些比較細(xì)致的問題,如下
創(chuàng)建Handler會(huì)引起內(nèi)存泄露裁着,如何避免繁涂?
內(nèi)部泄露的原因:Java中非靜態(tài)內(nèi)部類會(huì)默認(rèn)持有外部類的引用,如果你創(chuàng)建的Handler沒有使用靜態(tài)內(nèi)部類那么他會(huì)持有外部Activity或者Fragment的對(duì)象二驰,如過你Activity finish掉了扔罪,Handler還在Message隊(duì)列中沒有被處理還會(huì)持有Activity引用那就會(huì)內(nèi)存泄露,怎么解決兩種方式
1桶雀,使用靜態(tài)內(nèi)部類矿酵,靜態(tài)內(nèi)部類不持有外部類的應(yīng)引用所以沒事
2,使用軟引用或者弱引用
注意:有面試官會(huì)問可以創(chuàng)建幾個(gè)Handler矗积,我負(fù)責(zé)任的說是多個(gè)全肮,哪個(gè)Handler發(fā)送的消息哪個(gè)Handler處理(吐槽一下有的面試官,你自己把自己要問的問題搞清楚了在去問別人棘捣,非要跟我犟只能創(chuàng)建一個(gè))
3辜腺,創(chuàng)建Message
Message一般都是使用Message.obtain(),它這里面是有一個(gè)spool指向一個(gè)Message對(duì)象乍恐,還有一個(gè)next指向下一個(gè)Message评疗,它里面維護(hù)了一個(gè)鏈表,obtain的時(shí)候在表頭頭取Message禁熏,在Message回收的時(shí)候在表頭添加一個(gè)Message壤巷,類似棧,默認(rèn)大小是50
4瞧毙,消息的處理
Handler對(duì)象sendMessage發(fā)送消息放入的MessageQueue隊(duì)列中胧华,Looper輪訓(xùn)到它寄症,然后就開始處理Message,Message會(huì)有一個(gè)target去記錄是哪個(gè)Handler發(fā)送的它矩动,會(huì)調(diào)用這個(gè)Handler中的dispatchMessage()方法有巧,如果說Message中實(shí)現(xiàn)了CallBack那么調(diào)用Message中的CallBack,如果Handler中實(shí)現(xiàn)了Callback調(diào)用Handler中CallBack悲没,否則就都調(diào)動(dòng)Handler中的handleMessage方法
為什么在子線程中使用Handler會(huì)拋出異常篮迎?
根據(jù)上面的原理分析,那就是因?yàn)槟阕泳€程中沒有Looper示姿,給他一個(gè)Looper就好了