如何生動形象的理解Android Handler消息處理機(jī)制

? ? ? ? 在一個Android 程序開始運(yùn)行的時候啦辐,會單獨(dú)啟動一個Process。默認(rèn)的情況下劈猪,所有這個程序中的Activity昧甘,Service,Content Provider战得,Broadcast Receiver(Android 4大組件)都會跑在這個Process充边。一個Android 程序默認(rèn)情況下也只有一個Process,但一個Process下卻可以有許多個Thread常侦。在這么多Thread當(dāng)中浇冰,有一個Thread,我們稱之為UI Thread聋亡。UI Thread在Android程序運(yùn)行的時候就被創(chuàng)建肘习,是一個Process當(dāng)中的主線程Main Thread,主要是負(fù)責(zé)控制UI界面的顯示坡倔、更新和控件交互漂佩。在Android程序創(chuàng)建之初,一個Process呈現(xiàn)的是單線程模型罪塔,所有的任務(wù)都在一個線程中運(yùn)行投蝉。因此,我們認(rèn)為征堪,UI Thread所執(zhí)行的每一個函數(shù)瘩缆,所花費(fèi)的時間都應(yīng)該是越短越好。而其他比較費(fèi)時的工作(訪問網(wǎng)絡(luò)佃蚜,下載數(shù)據(jù)庸娱,查詢數(shù)據(jù)庫等)着绊,都應(yīng)該交由子線程去執(zhí)行,以免阻塞主線程熟尉,導(dǎo)致ANR归露。那么問題來了,UI 主線程和子線程是怎么通信的呢斤儿。這就要提到我們這里要講的Handler機(jī)制靶擦。

? ? ? ? ? 簡單來說,handler機(jī)制被引入的目的就是為了實(shí)現(xiàn)線程間通信的雇毫。handler一共干了兩件事:在子線程中發(fā)出message,在主線程中獲取踩蔚、處理message棚放。聽起來好像so easy,如果面試中讓你闡述下Handler機(jī)制馅闽,我們這么回答顯然不是面試官想要的答案飘蚯。我們忽略了一個最重要的問題:子線程何時發(fā)送message,主線程何時獲取處理message福也。

? ? ? ? ? 為了能讓主線程“適時”得處理子線程所發(fā)送的message局骤,顯然只能通過回調(diào)的方式來實(shí)現(xiàn)——開發(fā)者只要重寫Handler類中處理消息的方法,當(dāng)子線程發(fā)送消時暴凑,Handler類中處理消息的方法就會被自動回調(diào)峦甩。

? ? ? ? ? ?Handler類包含如下方法用于發(fā)送處理消息

? ? ? ? ? ?void handleMessage(Message msg):處理消息的方法,該方法通常用于被重寫现喳。

? ? ? ? ? ?final boolean hasMessage(int what):檢查消息隊列中是否包含what屬性為指定值的消息凯傲。

? ? ? ? ? ?final boolean hasMessage(int what,Object object):檢查消息隊列中是否包含what屬性為指定值且object屬性為指定對象的消息嗦篱。

? ? ? ? ? ?sendEmptyMessage(int what)發(fā)送空消息冰单。

? ? ? ? ? ?sendEmptyMessageDelayed(int what,longdelayMillis)灸促;指定多少毫秒之后發(fā)送空消息诫欠。

? ? ? ? ? ?sendMessage(Message msg)立即發(fā)送消息。

? ? ? ? ? ?sendMessageDelayed(int what浴栽,longdelayMillis)荒叼;指定多少毫秒之后發(fā)送消息。

? ? ? ? ? ?借助以上方法吃度,我們就可以自由穿梭于主線程和子線程之中了甩挫。

? ? ? ? ? ?到這里就結(jié)束了么?當(dāng)然沒有椿每。我要講的東西才剛剛開始伊者,要知道消息處理這件事英遭,不是handler一個人在戰(zhàn)斗,android的消息處理有三個核心類:Handler亦渗,Looper,和Message挖诸。其實(shí)還有一個MessageQueue(消息隊列),但是Message Queue被封裝到Looper里面了法精,我們不會直接與Message Queue打交道多律。

? ? ? ? ? ?Looper的字面意思是“循環(huán)裝置”,它被設(shè)計用來使一個普通線程變成Looper線程搂蜓。所謂Looper線程就是循環(huán)工作的線程狼荞。在程序開發(fā)中,我們經(jīng)常會需要一個線程不斷循環(huán)帮碰,一旦有新任務(wù)則執(zhí)行相味,執(zhí)行完繼續(xù)等待下一個任務(wù),這就是Looper線程殉挽。Looper是用于給一個線程添加一個消息隊列(MessageQueue)丰涉,并且循環(huán)等待,當(dāng)有消息時會喚起線程來處理消息的一個工具斯碌,直到線程結(jié)束為止一死。通常情況下不會用到Looper,因?yàn)閷τ贏ctivity傻唾,Service等系統(tǒng)組件投慈,F(xiàn)rameworks已經(jīng)為我們初始化好了線程(俗稱的UI線程或主線程),在其內(nèi)含有一個Looper冠骄,和由Looper創(chuàng)建的消息隊列逛裤,所以主線程會一直運(yùn)行,處理用戶事件猴抹,直到某些事件(BACK)退出带族。

? ? ? ? ? ?如果,我們需要新建一個線程蟀给,并且這個線程要能夠循環(huán)處理其他線程發(fā)來的消息事件蝙砌,或者需要長期與其他線程進(jìn)行復(fù)雜的交互,這時就需要用到Looper來給線程建立消息隊列跋理。

? ? ? ? ? ?使用Looper也非常的簡單择克,它的方法比較少,最主要的有四個:

? ? ? ? ? ? public static prepare();為線程初始化消息隊列前普。

? ? ? ? ? ? public static myLooper();獲取此Looper對象的引用

? ? ? ? ? ? public static loop();讓線程的消息隊列開始運(yùn)行肚邢,可以接收消息了。

? ? ? ? ? ? public void quit();退出具體哪個Looper

? ? ? ? ? ? 在整個消息處理機(jī)制中,message又叫task骡湖,封裝了任務(wù)攜帶的信息和處理該任務(wù)的handler贱纠,這個很好理解,就不做介紹了响蕴。

? ? ? ? ? ? 說了這么多谆焊,我知道你一定沒聽太明白。沒關(guān)系浦夷,我再對Handler運(yùn)行機(jī)制做個總結(jié):

? ? ? ? ? ?子線程(無looper)借用主線程(有l(wèi)ooper)里的Hander發(fā)送一條message到主線程辖试,這個message會被主線程放入message queue,主線程里面有一個looper劈狐,在輪詢message queue的時候發(fā)現(xiàn)有一條message罐孝。調(diào)用handler消息處理者,執(zhí)行handlemessage方法肥缔,去處理這個message肾档,就可以在handlemessage的方法里面更新ui。好像畫面感不是太強(qiáng)辫继,那我舉個例子吧。試想有一個生產(chǎn)方便面的車間俗慈,這個車間有兩條生產(chǎn)線姑宽,一條是生產(chǎn)面餅的闺阱,一條是生產(chǎn)調(diào)料包的炮车,面餅的生產(chǎn)線比較先進(jìn)一點(diǎn)瘦穆,配備了一個工人叫handler扛或,還配備了一個調(diào)料包分類循環(huán)器碘饼。這個車間能生產(chǎn)很多種方便面艾恼,有老壇酸菜,有泡椒鳳爪舆声,有香菇燉雞柳爽,有紅燒牛肉等等。其中方便面的面餅都是一樣的毙芜,只有調(diào)料包和包裝袋不一樣腋粥,包裝袋是根據(jù)調(diào)料包來定的。那么生產(chǎn)線運(yùn)作起來了:工人Handler把子生產(chǎn)線(子線程)上的調(diào)料包(message)放到了主生產(chǎn)線(主線程)上的調(diào)料包分類循環(huán)器(Looper)上闹瞧,通過輪詢分類篩選后工人Handler確定這是一包合格的老壇酸菜味調(diào)料包奥邮,于是工人把老壇酸菜調(diào)料包和面餅放在一塊(sendmessage)罗珍,告訴主生產(chǎn)線覆旱,這是一包老壇酸菜方便面扣唱,請給這包方便面包一個老壇酸菜的包裝袋(更新UI).

? 好了,我想這下你肯定懂了炼彪。

? ? ? ? ?(如有刊誤正歼,歡迎指正)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末齐疙,一起剝皮案震驚了整個濱河市旭咽,隨后出現(xiàn)的幾起案子穷绵,更是在濱河造成了極大的恐慌,老刑警劉巖勾缭,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件毒嫡,死亡現(xiàn)場離奇詭異兜畸,居然都是意外死亡碘梢,警方通過查閱死者的電腦和手機(jī)煞躬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進(jìn)店門恩沛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人芒珠,你說我怎么就攤上這事∽芊牛” “怎么了局雄?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵炬搭,是天一觀的道長宫盔。 經(jīng)常有香客問我灼芭,道長,這世上最難降的妖魔是什么巍佑? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任萤衰,我火速辦了婚禮脆栋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘糖耸。我一直安慰自己嘉竟,他們只是感情好洋侨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布希坚。 她就那樣靜靜地躺著裁僧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪茬底。 梳的紋絲不亂的頭發(fā)上阱表,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天最爬,我揣著相機(jī)與錄音爱致,去河邊找鬼寒随。 笑死,一個胖子當(dāng)著我的面吹牛逢防,可吹牛的內(nèi)容都是我干的忘朝。 我是一名探鬼主播局嘁,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼肴茄,長吁一口氣:“原來是場噩夢啊……” “哼寡痰!你這毒婦竟也來了拦坠?” 一聲冷哼從身側(cè)響起贞滨,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎骄噪,沒想到半個月后腰池,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年囱皿,在試婚紗的時候發(fā)現(xiàn)自己被綠了嘱腥。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片齿兔。...
    茶點(diǎn)故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖医寿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情盆偿,我是刑警寧澤事扭,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站罐农,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏气筋。R本人自食惡果不足惜宠默,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望融欧。 院中可真熱鬧蹬癌,春花似錦、人聲如沸董济。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吹埠。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間呻纹,已是汗流浹背雷酪。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工省骂, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留最住,地道東北人钞澳。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像涨缚,于是被迫代替她去往敵國和親轧粟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評論 2 354

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