從原始碼角度分析基礎的Handler訊息機制

2021-09-13 09:25:19 字數 3259 閱讀 7917

其實網上已經有很多寫的很好很優秀的文章了,我這裡就是想寫一篇來捋清思路,同時加深記憶。

handler訊息機制主要還是有5個元件,handler、looper、message、messagequeue、threadlocal

首先還是要明白,我們要傳輸的message是什麼,裡面有什麼東西。

public final class message implements parcelable
是不是都覺得挺熟悉的?好多都是我們寫方法需要用到的。

這裡介紹乙個 target,是handler型別的,即存放該message是哪個handler的message,這對我們理解後面部分有幫助。

例項化handler有7個構造方法

public handler() 

public handler(callback callback)

public handler(looper looper)

public handler(looper looper, callback callback)

public handler(boolean async)

public handler(callback callback, boolean async)

}mlooper = looper.mylooper();

if (mlooper == null)

mqueue = mlooper.mqueue;

mcallback = callback;

masynchronous = async;

}public handler(looper looper, callback callback, boolean async)

private boolean enqueuemessage(messagequeue queue, message msg, long uptimemillis) 

return queue.enqueuemessage(msg, uptimemillis);

}

以上**,將該message的target指向自己,傳送到messagequeue中,很好理解,下面來分析messagequeue的enququqmessage()

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的建構函式:

private looper(boolean quitallowed)
public static void preparemainlooper() 

smainlooper = mylooper();

}}

preparemainlooper主要還是用於建立主線程的looper,一般情況下,是禁止使用的,因為主線程的looper總是存在。並且可以看到,建立的主要方法還是prepare()。

private static void prepare(boolean quitallowed) 

sthreadlocal.set(new looper(quitallowed));

}

這裡的threadlocal即

static final threadlocalsthreadlocal = new threadlocal();
很顯然,這樣該執行緒的looper就建立出來,並且存到threadlocal中了。

那麼現在looper已經建立出來,如何運用它,把message傳送到messagequeue中呢?那就是loop()

public static void loop() 

final messagequeue queue = me.mqueue;

for (;;)

// this must be in a local variable, in case a ui event sets the logger

final printer logging = me.mlogging;

if (logging != null)

try finally

}}

刪去了些**,上面差不多是核心**。messagequeue本質上就是乙個單鏈表,loop用的是for(;; ),是乙個死迴圈,不停通過next獲取messagequeue的message,如果為空就直接return,否則通過msg.target.dispatchmessage(msg)將資訊傳送到msg.target這個handler型別的dispatchmessage中去。

那麼**就來到了handler中的dispatchmessage()中

public void dispatchmessage(message msg)  else 

}handlemessage(msg);

}}

這裡有一些判斷語句。在handler中,宣告了乙個介面callback,裡面只有乙個方法handlemessage,這個方法就是處理message訊息的,callback在構造方法中傳入。當然,若是在構造方法中沒有傳入callback的話還有一種方式,handler中也定義了乙個handlemessage方法,預設是個空實現。可以通過重寫這個方法來處理message訊息。

那麼這一整套流程就結束啦。

從原始碼角度分析RACObserve的實現原理(一)

racobserve是個巨集,racobserve target,keypath 最終是執行 target rac valuesforkeypath keypath target,keypath observer self 這就牽出nsobject racpropertysubscribing ca...

從原始碼角度分析 React 生命週期

使用過 react 框架開發的人,對 react 生命週期一定不會陌生,對 componentwillmount componentdidmount shouldcomponentupdate 等生命週期的運用必定輕車熟路,但是除了這些常用的生命週期,你知道還有 getdefaultprops ge...

從原始碼角度來看UVM phase

說到uvm phase我們就知道是uvm乙個很重要的特性,從使用者角度來講,其實就是一些很簡單的應用規則,能夠極大地提公升編碼的效率,簡化 複雜度,提高debug的效率。至於應用可以參看zhangqiang大佬的第五章,這裡就不再贅述。本文就從原始碼的角度來看,uvm的phase是怎麼工作的?之前學...