Android 訊息傳遞

2021-09-19 12:19:35 字數 3793 閱讀 7296

在建立handler時,handler在其構造方法中***嘗試從當前執行緒(建立hanlder例項物件的執行緒)的threadlocal中取到looper物件***,並將該looper物件賦值給當前hanlder物件,同時還會將looper物件的messagequeue引用賦值給當前handler。

public

static

@nullable looper mylooper()

//new handler()

public

handler

(callback callback,

boolean async)

mqueue = mlooper.mqueue;

mcallback = callback;

masynchronous = async;

}

在子執行緒中嘗試建立handler物件時,檢測當前執行緒是否已經關聯looper物件,不存在就報錯(需要呼叫looper.prepare()進行關聯),存在的話直接返回當前執行緒關聯的looper物件,使handler持有looper和looper.messagequeue的引用,從而能夠往messagequeue中新增訊息。乙個執行緒最多只能建立乙個looper,但是多個handler可以對應同乙個looper,只要在乙個執行緒中。

private

static

void

prepare

(boolean quitallowed)

sthreadlocal.

set(

newlooper

(quitallowed));

}

在主線程中建立handler不需要手動呼叫looper.prepare(),因為主線程的activitythread變數在main方法中呼叫了preparemainlooper()來初始化了主線程的looper物件。

public

static

void

main

(string[

] args)if(

false

) looper.

loop()

;}

handler的sendmessage呼叫的是messagequeue.enqueuemessage(message,uptimemillis),因為可能存在多個執行緒同時往同乙個messagequeue中插入message,所以messagequeue.enqueuemessage是同步方法sendmessage()最終呼叫sendmessageattime(),只不過它的uptimemillis引數為0,即不延時執行的意思。

public

final

boolean

sendmessage

(message msg)

public

final

boolean

sendmessagedelayed

(message msg,

long delaymillis)

return

sendmessageattime

(msg, systemclock.

uptimemillis()

+ delaymillis)

;}

這裡的uptimemillis隨msg存入到mq,而sendmessagedelayed()的延遲執行效果是有mq在取出訊息進行dispatch時完成的,取出訊息時會比對當前時間和msg的when屬性。

public

boolean

sendmessageattime

(message msg,

long uptimemillis)

return

enqueuemessage

(queue, msg, uptimemillis);}

private

boolean

enqueuemessage

(messagequeue queue, message msg,

long uptimemillis)

return queue.

enqueuemessage

(msg, uptimemillis);}

boolean

enqueuemessage

(message msg,

long when)

if(msg.

isinuse()

)synchronized

(this

) msg.

markinuse()

; msg.when = when;

message p = mmessages;

boolean needwake;

if(p == null || when ==

0|| when < p.when)

else

if(needwake && p.

isasynchronous()

)}msg.next = p;

// invariant: p == prev.next

prev.next = msg;

}// we can assume mptr != 0 because mquitting is false.

if(needwake)

}return

true

;}

looper呼叫loop()方法,其中不斷從messagequeue中取出message(通過message.next()方法),進行dispatchmessage,其實在handler呼叫sendmessage時已經將自己設定為message.target了,所以dispatch只是將message發給自己的target處理而已

定義乙個全域性的handler物件mhandler;在子執行緒a中初始化這個mhandler,並重寫handlermessage()方法;在子執行緒b中呼叫mhandler.obtainmessage()方法從message類自帶的message pool中返回乙個message物件,然後使用message.sendtotarget()方法,傳送訊息。

public

static

void

loop()

...}

...}

首先需要知道造成anr的原因:

當前的事件沒有機會得到處理(即主線程正在處理前乙個事件,沒有及時的完成或者looper被某種原因阻塞住了)。

**當前的事件正在處理,但沒有及時完成。**執行時間超過了anr的閾值:按鍵事件 5s ,broadcast 10s、前台service無響應的超時時間為20秒,後台service為200秒。

這樣就可以解釋為什麼主線程的looper.loop()一直無限迴圈但是為什麼沒有造成anr了,從上面的**可以看出當沒有message需要處理時,主線程沒有進行任何和造成anr有關的事件的處理,雖然是在無限迴圈,但是比起頻繁的開啟、關閉訊息迴圈動作,這樣的開銷反而更小吧。

Android訊息傳遞之元件間傳遞訊息

前言 上篇學習總結了android通過handler訊息機制實現了工作執行緒與ui執行緒之間的通訊,今天來學習一下如何實現元件之間的通訊。本文依然是為學習eventbus做鋪墊,有對比才能進步,今天主要介紹在eventbus出現之前的實現方式,通過intent方式這裡不做介紹。需求場景 方式一 通過...

Android 訊息傳遞機制分析

android系統出於系統優化的原因,ui執行緒操作並不是執行緒安全的,這意味著如果多執行緒併發操作ui元件,則可能導致執行緒執行緒安全。所以為了解決這個問題,android制定了一條規則 只允許ui執行緒修改activity裡的ui元件。當乙個程式啟動第一次啟動時,android會同時啟動一條主線...

Android中Handler訊息傳遞機制

因為是在專案中的收穫,所以不全,以後遇到其他的我會加上。安卓中用handler機制來實現主線程和子執行緒之間的通訊,通訊的媒介是message的例項。首先要在主線程宣告乙個handler物件,然後重寫裡面的handmessage message msg 方法,用switch case語句進行匹配處理...