亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁(yè) > 系統(tǒng) > Android > 正文

深入淺析Android消息機(jī)制

2019-12-12 06:41:36
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

在Android中,線程內(nèi)部或者線程之間進(jìn)行信息交互時(shí)經(jīng)常會(huì)使用消息,這些基礎(chǔ)的東西如果我們熟悉其內(nèi)部的原理,將會(huì)使我們?nèi)菀住⒏玫丶軜?gòu)系統(tǒng),避免一些低級(jí)的錯(cuò)誤。

每一個(gè)Android應(yīng)用在啟動(dòng)的時(shí)候都會(huì)創(chuàng)建一個(gè)線程,這個(gè)線程被稱為主線程或者UI線程,Android應(yīng)用的所有操作默認(rèn)都會(huì)運(yùn)行在這個(gè)線程中。
但是當(dāng)我們想要進(jìn)行數(shù)據(jù)請(qǐng)求,圖片下載,或者其他耗時(shí)操作時(shí),是不可能在這個(gè)UI線程做的,因?yàn)锳ndroid在3.0以后的版本已經(jīng)禁止了這件事情,直接拋出一個(gè)異常。所以我們需要一個(gè)子線程來(lái)處理那些除UI操作的事情。

但是這個(gè)又會(huì)有一個(gè)問題,我們只能在UI線程進(jìn)程UI操作,只能在子線程進(jìn)行耗時(shí)操作,如果我們需要在耗時(shí)操作結(jié)束后在Android界面上顯示一個(gè)View,我們應(yīng)該怎么做?我們是不可能在子線程直接刷新UI的。這時(shí)我們需要用到Android的消息機(jī)制,來(lái)實(shí)現(xiàn)主線程和子線程的通信。簡(jiǎn)單來(lái)說(shuō),就是子線程獲取到數(shù)據(jù)之后,不直接進(jìn)行UI更新,而是把數(shù)據(jù)裝到消息中發(fā)送到主線程,主線程中有一個(gè)循環(huán)輪詢會(huì)立即收到子線程發(fā)過來(lái)的信息,然后拿到消息數(shù)據(jù)后在主線程更新UI 。說(shuō)起來(lái)比較簡(jiǎn)單,我們來(lái)仔細(xì)的看一下具體是怎么說(shuō)的。

處理消息的手段――Handler, Looper, MessageQueue

Handler

我們先講解一下Handler,Handler顧名思義就是處理者,通常對(duì)他的用法是在UI線程中新建一個(gè)Handler,并覆寫他的handleMessage, 然后再耗時(shí)的線程中將消息post給UI線程,例子如下:

class MyHandler extends Handler{@Overridepublic void handleMessage(Message msg){//更新UI}}MyHandler mHandler = new MyHandler();new Thread(){public void run(){mHandler.sendEmptyMessage(123);};}.start(); 

這里規(guī)定了Handler必須在主線程創(chuàng)建,因?yàn)橹挥性赨I線程創(chuàng)建才會(huì)讓Handler關(guān)聯(lián)到已有的MessageQueue。而MessageQueue被封裝到Looper中,而Looper又通過ThreadLocal封裝到一個(gè)線程中,最后相當(dāng)于MessageQueue關(guān)聯(lián)了一個(gè)線程。所以簡(jiǎn)單來(lái)說(shuō)就是Handler將消息投遞到一個(gè)關(guān)聯(lián)了線程的MessageQueue中,然后Handler在從MessageQueue中取出消息,并且處理它。

我們看一下Handler的2個(gè)常用的方法

void handleMessage(Message msg) : 處理消息的方法final boolean sendMessage(Message msg) : 立即發(fā)送消息

第一個(gè)方法 我們通常在UI線程中執(zhí)行,一般用來(lái)刷新UI,至于如果創(chuàng)建了一個(gè)非靜態(tài)內(nèi)部類產(chǎn)生對(duì)內(nèi)存泄漏,建議參考這篇博客Handler引發(fā)的內(nèi)存泄漏.第二個(gè)方法我們通常在子線程中執(zhí)行,需要一個(gè)Handler的實(shí)例化對(duì)象,通常是由主線程去去傳遞給子線程。并且需要一個(gè)Message對(duì)象,指定他的msg.what作為消息的標(biāo)示,但是如果我們只是用Handler去處理一個(gè)消息的時(shí)候,選擇post方法是個(gè)更好的選擇,例子如下:

private Handler mHandler = new Handler();new Thread(new Runnable() {@Overridepublic void run() {mHandler.post(new Runnable() {@Overridepublic void run() {//UI操作...}});}}).start(); 

下面我們接著討論下消息的循環(huán)隊(duì)列MessageQueue與包裝他的Looper循環(huán)

Looper和MessageQueue

上面提到了在UI線程中創(chuàng)建并實(shí)例化Handler對(duì)象不需要Looper和MessageQueue,因?yàn)槲覀兊膽?yīng)用在啟動(dòng)的時(shí)候先執(zhí)行了ActivityThreadMain,在這個(gè)方法就是Java語(yǔ)言運(yùn)行的入口public

static void main(String [] args) 在這里面創(chuàng)建了一個(gè)MainLooper,創(chuàng)建的過程如下:public static void main(string[] args){//初始化Looper.prepareMainLooper();ActivityThread thread = new ActivityThread();thread.attach(false);if(sMainThreadHandler == null){sMainThreadHandler = thread.getHandler();}AsyncTask.init();//動(dòng)起來(lái)Looper.loop();} 

這里面并沒有MessageQueue的出現(xiàn),我們可以看一看Looper類的源碼,來(lái)了解在初始化的時(shí)候發(fā)生了什么有趣的事情。

public class Looper {private static final ThreadLocal sThreadLocal = new ThreadLocal();// Looper內(nèi)的消息隊(duì)列final MessageQueue mQueue;// 當(dāng)前線程Thread mThread;// 。。。其他屬性// 每個(gè)Looper對(duì)象中有它的消息隊(duì)列,和它所屬的線程private Looper() {mQueue = new MessageQueue();mRun = true;mThread = Thread.currentThread();}// 我們調(diào)用該方法會(huì)在調(diào)用線程的TLS中創(chuàng)建Looper對(duì)象public static final void prepare() {if (sThreadLocal.get() != null) {// 試圖在有Looper的線程中再次創(chuàng)建Looper將拋出異常throw new RuntimeException("Only one Looper may be created per thread");}sThreadLocal.set(new Looper());}// 其他方法} 

我們一行行的看這段代碼,首先是實(shí)例化一個(gè)ThreadLocal對(duì)象,這個(gè)用來(lái)實(shí)現(xiàn)Looper循環(huán)的本地化存儲(chǔ),關(guān)于ThreadLocal可以看這篇文章為什么用ThreadLocal,簡(jiǎn)而言之就是當(dāng)多個(gè)線程同時(shí)訪問Looper對(duì)象的時(shí)候,我們不用synchronized同步機(jī)制來(lái)處理他,而是為每個(gè)線程創(chuàng)建一個(gè)自己的Looper副本,A線程改變了A的looper副本,不影響B(tài)線程的Looper,從而比較高效的實(shí)現(xiàn)線程安全。后面幾句依次定義了MessageQueue,并對(duì)Looper進(jìn)行了私有化構(gòu)造,在prepare方法中將Looper對(duì)象設(shè)置給了sThreadLocal 這樣MessageQueue包裝在了Looper對(duì)象中,同時(shí)通過ThreadLocal使得線程和Looper關(guān)聯(lián)上,從而消息隊(duì)列與線程關(guān)聯(lián)上,并且不同的線程就不能訪問對(duì)方的消息隊(duì)列。

如下圖所示:

接著就是Looper.loop 循環(huán)執(zhí)行起來(lái),我們看一下,在loop方法里面執(zhí)行了發(fā)生了什么事情

public static final void loop() {Looper me = myLooper(); //得到當(dāng)前線程LooperMessageQueue queue = me.mQueue; //得到當(dāng)前l(fā)ooper的MQwhile (true) {Message msg = queue.next(); // 取出messageif (msg != null) {if (msg.target == null) {return;}msg.target.dispatchMessage(msg);msg.recycle();}}}

這是省略版的代碼,我們從這里看出無(wú)限循環(huán)執(zhí)行,首先從消息隊(duì)列中不斷取出消息,然后不斷msg是否為空,msg.target是否為空,不空的話,執(zhí)行dispatchMessage方法,這個(gè)方法是handler的一個(gè)方法,由此我們可以看出msg.target是handler的類型,至此,通過Looper.prepare和Loop.loop實(shí)現(xiàn)了MessageQueue,Looper,Handler三者之間的關(guān)聯(lián)。而Handler與Looper,和MessageQueue關(guān)聯(lián)則是在Handler的默認(rèn)構(gòu)造器中,通過Looper.getLooper獲取loop對(duì)象,從而獲取MessageQueue,其源碼如下:

public Handler(){//直接把關(guān)聯(lián)looper的MQ作為自己的MQ,因此它的消息將發(fā)送到關(guān)聯(lián)looper的MQ上mLooper = Looper.myLooper();mQueue = mLooper.mQueue;mCallback = null;}

然后我們的流程圖可以多些內(nèi)容,如下所示:

我們接下來(lái)看一下dispatchMessage() 方法,在該方法中實(shí)際上只是一個(gè)分發(fā)方法,如果Runable類型的callback為空,則執(zhí)行handlerMessage來(lái)處理消息,該方法為空,需要覆寫。如果不為空,則執(zhí)行handleCallback。實(shí)際上,如果我們用handle的post方法,則就執(zhí)行了callback,如果用sendMessage,則就執(zhí)行了handleMessage
這里無(wú)論是post(Runnable callback)還是handlerMessage實(shí)際上都是在調(diào)用一個(gè)方法sendMessageDelayed(Message msg) 只不過handlerMessage是直接接受一個(gè)參數(shù),而Runable callback實(shí)際上是將這個(gè)Runable對(duì)象賦給了Message對(duì)象的callback成員變量,最后將Message對(duì)象插入消息隊(duì)列里面。最后Looper不斷從MessageQueue中讀取消息,并且調(diào)用Handler的dispatchMessage消息,在根據(jù)callback是否為空,來(lái)采用不同的方法執(zhí)行。Android消息機(jī)制分析到此結(jié)束。

回到最開始

我們這次知道了為什么要在主線程中實(shí)例化Handler對(duì)象才能更新UI刷新,因?yàn)橹挥邪l(fā)送到UI線程的消息,才能被UI線程的handler處理,如果我們要在非UI線程中,實(shí)例化Handler,則必須先將線程變成LooperThread,在實(shí)例化。也就是說(shuō)執(zhí)行如下的代碼:

Loop.prepare();hander = new Handler;

Loop.loop

至于原因相信讀完上面的講解,應(yīng)該知道。
現(xiàn)在我們看一下我們最開始的代碼,最后腦補(bǔ)一下Handler的工作流程。

class MyHandler extends Handler{@Overridepublic void handleMessage(Message msg){//更新UI}}MyHandler mHandler = new MyHandler();new Thread(){public void run(){mHandler.sendEmptyMessage(123);};}.start(); 

在Handler實(shí)例化成mHandler的時(shí)候,系統(tǒng)通過Handler默認(rèn)的構(gòu)造函數(shù)完成了Handler與Looper的關(guān)聯(lián),并通過Looper關(guān)聯(lián)到了MessageQueue。而主線程的Looper則早在系統(tǒng)啟動(dòng)的時(shí)候通過Loop.prepare就已經(jīng)構(gòu)造完成了,并與UI線程通過ThreadLocal關(guān)聯(lián)起來(lái),然后在新的線程中執(zhí)行mHandler.sendEmptyMessage,將Message發(fā)送給了MessageQueue,Looper.loop在循環(huán)的時(shí)候,不斷取出message,交給Handler處理,在我們覆寫的HandleMessage中,識(shí)別出我們發(fā)送的消息,將消息處理。當(dāng)然這里只是一個(gè)Empty消息,所以在handleMessage中沒有去執(zhí)行msg.what的判斷。

以上內(nèi)容是小編給大家介紹的Android消息機(jī)制,希望對(duì)大家有所幫助!

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
国产精品视频免费在线| 都市激情国产精品| 综合伊思人在钱三区| 亚洲最大福利视频网站| 成人午夜视频免费在线观看| 91亚洲一区二区| 欧美尤物巨大精品爽| 国产综合视频在线观看| 一区二区国产欧美| 在线国产欧美| 国语对白在线视频| 亚洲精品成人三区| 中文字幕第66页| 99亚偷拍自图区亚洲| 国产欧美综合精品一区二区| av在线网址观看| 又色又爽又高潮免费视频国产| 色阁综合伊人av| 欧美边添边摸边做边爱免费| 色综合天天综合网国产成人综合天| 在线观看网站免费入口在线观看国内| 国产精品毛片一区二区| 岛国视频免费在线观看| 在线观看精品视频| www.一区二区三区| 成人av电影在线网| 男人的天堂日韩| 在线人成动漫视频在线观看| 国产在线日韩欧美| 在线观看av大片| 亚洲精品欧美二区三区中文字幕| 天堂在线中文视频| 欧美视频一二三| 中文字幕中文字幕一区三区| 一区二区三区久久| 一区二区三区91| 91精品国产综合久久国产大片| 国产噜噜噜噜噜久久久久久久久| 91传媒理伦片在线观看| 久久精品国产av一区二区三区| 成人av在线播放观看| 国产日韩欧美在线播放| 日本免费一区视频| 国产91沈先生在线播放| 天干天干啦夜天干天2019| 国产字幕在线看| 欧美专区在线视频| 7878成人国产在线观看| 97视频在线观看网站| 国产美女喷水视频| 欧美日韩一视频区二区| 久久99国产乱子伦精品免费| 欧美在线一级视频| 免费成人深夜夜行网站| 成人高清一区| 免费观看又色又爽又黄的网站| 成人夜色视频网站在线观看| 中文字幕免费在线不卡| 亚洲日本乱码在线观看| 香港成人在线视频| 成人在线免费观看av| 亚洲欧美日韩国产中文在线| 亚洲国产成人精品女人| 欧美一级一级性生活免费录像| 成人免费的视频| 国产免播放器视频| 可以直接看的av网址站| 亚洲欧美综合另类| 亚洲激情在线观看视频免费| 日本丰满少妇xxxx| 国产激情片在线观看| 特级黄国产片一级视频播放| 亚洲自拍偷拍二区| 日韩女优电影在线观看| 国产日本韩国在线播放| eeuss性xxxxxx电影| 外国成人直播| av在线网址导航| 波多野结衣黄色网址| 女人被男人躁得好爽免费视频| 国产精品第一国产精品| 91精品国产自产91精品| 97久久人国产精品婷婷| 粉嫩aⅴ一区二区三区| 国产69精品久久久久按摩| 久久人妻精品白浆国产| 欧洲午夜精品久久久| 中文字幕一区电影| 在线精品免费视| 97在线观看免费视频| 国产精品一区二区人人爽| 国产一区免费观看| 欧美国产精品一区二区三区| 国语自产精品视频在线看一大j8| 欧美精品一区二区三区四区五区| 在线观看麻豆视频| 色av一区二区三区| 欧美男女性生活在线直播观看| 日韩一区二区视频在线| 日韩一区二区电影| 日韩三区在线观看| 天堂蜜桃91精品| 蜜桃自拍偷拍| 欧美性视频在线播放| 波多野结衣一二三区| 国产aaaaaaaaa| aaaaaa亚洲| 国产精品1区在线| 久久久久99精品| 成年人看片网站| 亚洲无限乱码一二三四麻| 青青久久av| 欧美高清不卡| 色欲色香天天天综合网www| 亚欧在线观看视频| 精品亚洲免费视频| 国语对白在线视频| 一区二区三区在线播放欧美| 欧美高清性xxxxhd| 黄色网在线播放| 欧美伊人影院| 老司机凹凸av亚洲导航| 日本在线视频www鲁啊鲁| 亚洲春色在线| 一二三四区视频| 凹凸精品一区二区三区| 成人午夜福利视频| 久久久久国产精品麻豆| 欧美图片欧美激情欧美精品| 久久天天躁狠狠躁夜夜爽蜜月| 欧美一级片久久久久久久| 成人羞羞视频免费| 亚洲欧美偷拍另类a∨色屁股| 在线视频亚洲自拍| 日韩视频www| 国产午夜精品久久久久久久| 婷婷在线播放| 高清视频在线www色| 精品视频999| 国产欧美日韩成人| 波霸ol色综合久久| 国产av无码专区亚洲av麻豆| 人人妻人人澡人人爽精品日本| 久久精品美女视频网站| 欧美精品中文字幕亚洲专区| 欧美日韩不卡一区二区| 久久这里只有精品免费| 51漫画成人app入口| 成人国产精品久久久| 国产极品人妖在线观看| 青青草av在线播放| 精品国产一区二区三区久久久狼牙| 免费一区二区| 濑亚美莉大战黑人中文字幕| 国产综合视频一区二区三区免费| 国产美女www爽爽爽| 天堂色在线视频| 欧美日韩国产精品一区二区亚洲| 欧美亚洲色综久久精品国产| 男人的天堂视频在线| 精品粉嫩aⅴ一区二区三区四区| 欧美变态xxxx| 亚洲精品少妇一区二区| 国内精品美女在线观看| 久久日韩精品| 日本韩国精品一区二区在线观看| 亚洲人成网7777777国产| 在线免费观看黄色小视频| 久久久久久亚洲av无码专区| 欧美精品一卡| 日本福利专区在线观看| 国产一级特黄a大片免费| 黄色一级片在线| 女同一区二区三区| 成人午夜免费在线| 欧美午夜精品久久久久久蜜| 国产精华7777777| 亚洲欧洲一二区| 久久蜜桃资源一区二区老牛| 91大神网址| 一区二区三区韩国| 久久亚洲国产中v天仙www| 一区二区三区在线观看国产| 国产亚洲欧美日韩在线观看一区二区| 亚洲欧洲视频在线观看| 国产一二三区精品| 久久免费公开视频| 成年女人在线看片| 国产大片精品免费永久看nba| 小说区图片区色综合区| 色综合中文综合网| 久久国产欧美| 久久成人国产精品入口| 日本精品久久久久久久久久| 网友自拍视频在线| 欧美与欧洲交xxxx免费观看| 欧美日韩中文字幕精品| 老鸭窝91久久精品色噜噜导演| 精品女同一区二区三区| 日韩大尺度黄色| 国产日韩在线观看视频| 夜夜骚av一区二区三区| 在线不卡一区二区三区| 日韩精品亚洲元码| 国产精品久久久久一区二区三区| 亚洲综合激情另类专区老铁性| 欧美成人午夜视频| 日本亚洲视频在线| 7777kkk亚洲综合欧美网站| 成人亚洲精品777777大片| 日日日日人人人夜夜夜2017| 在线国产中文字幕| 色老头一区二区三区在线观看| 国产裸舞福利在线视频合集| 免费黄色在线网址| 日韩精品专区在线| 舔着乳尖日韩一区| 天天操天天怕| 青草青青国产| 中文字幕91爱爱| 精品对白一区国产伦| 欧美小视频在线观看| 中文字幕乱码无码人妻系列蜜桃| 亚洲一本大道| 国产网站欧美日韩免费精品在线观看| 精品在线免费观看视频| 日韩在线观看视频一区二区| 日韩精品一区不卡| 欧美性大战久久久久xxx| 亚洲午夜精品视频| 黑人巨大精品欧美一区二区桃花岛| 91麻豆成人精品国产| 一色屋成人免费精品网| 黑人巨大40cm重口| 日韩精品中文字幕在线一区| 偷拍女澡堂一区二区三区| 欧美天天综合色影久久精品| baoyu135国产精品免费| 中文字幕一区二区5566日韩| 国产美女视频一区| 国产91精品免费| 久久久久久久久久影视| 国产调教一区二区三区| 7777精品伊人久久久大香线蕉| 国产成人自拍高清视频在线免费播放| www.99r| 日韩久久午夜影院| 国产精品伦理一区二区| 日韩电影一区二区三区四区| 欧美精选视频在线观看| 99国产精品久久一区二区三区| 久久偷拍免费视频| 91精品国产91久久久久久黑人| 国产高清不卡av| 91精品国产免费久久综合| 国产风韵犹存在线视精品| 爱爱免费视频网站| 中文字幕在线永久在线视频2020| 亚洲性在线观看| 色啪免费观看视频| 97成人精品视频在线观看| 色婷婷在线视频观看| 久久久亚洲欧洲日产| 国产精品入口福利| 成人免费视频国产| h1515四虎成人| 国产中文字幕在线| 竹内纱里奈兽皇系列在线观看| 亚洲老司机在线| 羞羞视频在线观看欧美| 亚洲免费观看在线观看| 好男人香蕉影院| 另类综合图区| 日韩精品视频中文在线观看| 天天射—综合中文网| 欧美孕妇孕交黑巨大网站| 国产精品久久久久久久成人午夜| 国产哺乳奶水91在线播放| 欧美一区二区三区在线免费观看| 亚洲黄色中文字幕| 亚洲欧美日韩一区在线观看| 91极品视觉盛宴| 久久久久久视频| 日韩深夜视频| 久久人人爽爽爽人久久久| 日韩一区在线视频| 国产三级三级三级看三级| 国产一区在线免费| 三级一区在线视频先锋| 91国模大尺度私拍在线视频| 欧美亚洲国产日韩| 久久久久久这里只有精品| 国产又粗又猛又黄| 在线精品国产亚洲| 国产第一页第二页| 午夜啪啪小视频| 91久热免费在线视频| 国产精品人人爱一区二区白浆| 美女被人操视频在线观看| 久久久精品网| 91视频免费版污| 国产精品久久久久久久久久免费看| 狠狠色综合色综合网络| 国产精品区在线| ww亚洲ww在线观看国产| 依依成人综合视频| 欧美激情四色| 男人添女人下部高潮视频在观看| 亚洲综合首页| 九七电影韩国女主播在线观看| 国产精品久久久久9999小说| 一本一道精品欧美中文字幕| 日韩亚洲天堂| 国产美女精彩久久| 天天操天天射天天色| 激情欧美日韩一区二区| 国产精品久久中文| 又黄又爽又色视频| 欧美专区日韩视频| bestiality新另类大全| 亚洲av无码一区东京热久久| 亚洲欧美日本伦理| 日本韩国在线视频爽| 亚洲高清免费| 四虎www4hu永久免费| 免费无码国产精品| 精品高清久久| 欧美午夜激情视频|