從另一個(gè)角度解讀handler原理

hello~辨图,大家好班套,我叫石頭。
這幾天在重新梳理Android開發(fā)相關(guān)的知識(shí)點(diǎn)故河,今天在梳理hanlder的時(shí)候吱韭,突然感受是不是可以換一個(gè)角度來梳理handler的原理,這樣可能更有助于理解handler鱼的,接下來設(shè)計(jì)到的知識(shí)點(diǎn)有內(nèi)存理盆, 線程java內(nèi)存模型等相關(guān)概念凑阶。
假如我們一個(gè)引用的內(nèi)存有這些線程猿规,handler,looper是不是有點(diǎn)暈乎乎的

多線程宙橱,多l(xiāng)ooper姨俩,多handler

下面我們就從另外一個(gè)角度切入,看看代碼究竟是怎么流轉(zhuǎn)的师郑。


下面我會(huì)用大量的圖片展示handler在時(shí)間上內(nèi)存的變化模型(內(nèi)存只展示了相關(guān)的變量跟概念)

一個(gè)初始化的項(xiàng)目

當(dāng)我們新建一個(gè)項(xiàng)目环葵,什么代碼都沒寫的時(shí)候,hanlder相關(guān)的內(nèi)存如下


初始內(nèi)存模型

這個(gè)時(shí)候我們有一個(gè)主線程(或者叫UI線程)宝冕,這個(gè)時(shí)候系統(tǒng)會(huì)默認(rèn)幫我們綁定了一個(gè)looper對(duì)象

我們Activity的LifeCycler回調(diào)就是這個(gè)默認(rèn)looper來分發(fā)的张遭。

Q:現(xiàn)在我們模擬一個(gè)場(chǎng)景就是:
界面元素: 1個(gè)Button, 1個(gè)TextView
任務(wù):點(diǎn)擊Button新開一個(gè)子線程地梨,在里面執(zhí)行我們需要的一些耗時(shí)操作菊卷,之后通過主線程更新TextView

我們用偽代碼模擬下

第一步:創(chuàng)建Handler對(duì)象

Handler handler = new Handler(){
    @Override
    public void handleMessage(@NonNull Message msg) {
        switch (msg.what){
            case 1:
                // 處理UI更新
                textView.setText("xxx");
                break;
        }
    }
}

這里我們思考一下handleMessage里面的代碼是在哪個(gè)線程里面執(zhí)行,如果我們把handler跟另外一個(gè)looper綁定宝剖,又會(huì)在哪個(gè)線程執(zhí)行handleMessage里面的代碼的烁,后面我會(huì)給出答案.

建立handler對(duì)象

第二步:添加Button點(diǎn)擊事件

點(diǎn)擊Button新開一個(gè)子線程,在里面執(zhí)行我們需要的一些耗時(shí)操作

Button button = findViewById(R.id.xxx);
button.setOnClickListener(v -> {
    new Thread(() -> {
        // 做一些耗時(shí)操作
        doSomeWork();
    });
});
子線程做耗時(shí)操作

第二步:在子線程中通過hander發(fā)送消息

Button button = findViewById(R.id.xxx);
button.setOnClickListener(v -> {
    new Thread(() -> {
        // 做一些耗時(shí)操作
        doSomeWork();
        Message msg = Message.obtain();
        msg.what = 1; //消息的標(biāo)識(shí)
        msg.obj = "子線程想發(fā)送給主線程的數(shù)據(jù)"; // 消息的存放
        handler.sendMessage(msg);
    });
});
找到handler引用

這里主要想說明2點(diǎn):
1.handler不是線程私有對(duì)象诈闺,所有能在子線程中通過其引用調(diào)用發(fā)送消息的方法.
2.looper是線程私有的渴庆,我們的消息最終會(huì)到達(dá)消息隊(duì)列(消息隊(duì)列在looper對(duì)象中)


在子線程通過handler引用調(diào)用sendMessage方法

第三步:在handler的handleMessage中處理消息

在主線程中調(diào)用handleMessage處理消息

到這里我們的邏輯就完成了
但是我們要思考的是:
其實(shí)我們所謂的在子線程中發(fā)送消息消息,在主線程中處理消息,其實(shí)說白了都是在利用handler對(duì)象來處理的
因?yàn)閔andler沒有對(duì)象到線程中去襟雷,所以任何線程只要能拿到他的引用都能對(duì)其進(jìn)行操作

  1. 子線程中發(fā)送消息消息:我們知道一個(gè)Thread類的run方法是運(yùn)行在子線程中的刃滓,所以在其中執(zhí)行handler.sendMessage(msg);方法也就是在子線程中。
  2. 主線程中處理消息: 我們知道Message是被looper從MessageQueue取出耸弄,并且通過其中handler引用調(diào)用到了handleMessage中咧虎,looper是被主線程私有的,并且是在主線程中的run方法中輪詢處理的计呈,所以這段代碼就是在主線程中執(zhí)行的.

總結(jié)一下就是
發(fā)送消息是在子線程的run方法進(jìn)行的砰诵,處理消息是在主線程的run方法進(jìn)行的,中間的邏輯紐帶是handler的引用捌显。


所謂的一段代碼在哪個(gè)線程中運(yùn)行茁彭,就是說的這段代碼的調(diào)用鏈?zhǔn)窃谀膫€(gè)線程的run中被調(diào)用的


進(jìn)階思考

Q1: HandlerThread使用中的handler中的sendMessage是在哪個(gè)線程中?
Q2: HandlerThread使用中的handler中的handleMessage是在哪個(gè)線程中扶歪?
Q3: 怎么在子線程1中發(fā)送消息理肺,在子線程2中處理消息?
Q4: 一個(gè)線程能有幾個(gè)looper善镰,幾個(gè)handler(這個(gè)問法不太嚴(yán)謹(jǐn)妹萨,想想為啥)?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末炫欺,一起剝皮案震驚了整個(gè)濱河市乎完,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌品洛,老刑警劉巖囱怕,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異毫别,居然都是意外死亡娃弓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門岛宦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來台丛,“玉大人,你說我怎么就攤上這事砾肺⊥烀梗” “怎么了?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵变汪,是天一觀的道長(zhǎng)侠坎。 經(jīng)常有香客問我,道長(zhǎng)裙盾,這世上最難降的妖魔是什么实胸? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任他嫡,我火速辦了婚禮,結(jié)果婚禮上庐完,老公的妹妹穿的比我還像新娘钢属。我一直安慰自己,他們只是感情好门躯,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布淆党。 她就那樣靜靜地躺著,像睡著了一般讶凉。 火紅的嫁衣襯著肌膚如雪染乌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天懂讯,我揣著相機(jī)與錄音荷憋,去河邊找鬼。 笑死域醇,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蓉媳。 我是一名探鬼主播譬挚,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼酪呻!你這毒婦竟也來了减宣?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤玩荠,失蹤者是張志新(化名)和其女友劉穎漆腌,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阶冈,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡闷尿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了女坑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片填具。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖匆骗,靈堂內(nèi)的尸體忽然破棺而出劳景,到底是詐尸還是另有隱情,我是刑警寧澤碉就,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布盟广,位于F島的核電站,受9級(jí)特大地震影響瓮钥,放射性物質(zhì)發(fā)生泄漏筋量。R本人自食惡果不足惜烹吵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望毛甲。 院中可真熱鬧年叮,春花似錦、人聲如沸玻募。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽七咧。三九已至跃惫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間艾栋,已是汗流浹背爆存。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蝗砾,地道東北人先较。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像悼粮,于是被迫代替她去往敵國(guó)和親闲勺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359