Handler原始碼分析

2021-10-01 14:10:47 字數 4220 閱讀 2623

當程式執行時,會先執行activitythreadmain方法。會執行looper.preparemainlooper()方法和looper.loop()方法。

looper.preparemainlooper()

public

static

void

preparemainlooper()

smainlooper =

mylooper()

;}}

其中又會進入prepare方法中,會發現呼叫了sthreadlocal.set(new looper(quitallowed));其中通過new looper()方法

private

looper

(boolean quitallowed)

對messagequeue佇列進行了初始化。

set方法:

public

void

set(t value)

將當前主線程新增到sthreadlocal中。通過static final threadlocalsthreadlocal = new threadlocal()設定靜態實現保證其唯一性。

looper.loop()

final looper me =

mylooper()

;if(me == null)

final messagequeue queue = me.mqueue;

首先通過mylooper()方法,

public

static

@nullable looper mylooper()

拿到存入的主線程的looper物件值,然後再拿到messagequeue物件,

其中

for(;

;)finally}.

....

.}

我們可以發現通過queue.next()拿到佇列中先進先出的值,使用msg.target.dispatchmessage(msg);進行分發,其中msg.target為handler(在message類中我們可以找到handler target的定義)。

我們在子執行緒中通過handler1.sendmessagedelayed(message,3000);進行傳送資料,最後都會呼叫到handler中的sendmessageattime()方法,

public

boolean

sendmessageattime

(message msg,

long uptimemillis)

return

enqueuemessage

(queue, msg, uptimemillis)

;}

然後呼叫enqueuemessage()方法,

private

boolean

enqueuemessage

(messagequeue queue, message msg,

long uptimemillis)

return queue.

enqueuemessage

(msg, uptimemillis)

;}

在此方法中對message的target屬性進行了賦值。

然後通過messagequeue類queue.enqueuemessage(msg, uptimemillis)進行佇列的填充。

其中主要**為:

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;

}

將定義的全域性的mmessages拿到,進行非空判定,若為空則直接新增到佇列首位。不為空,則通過鍊錶的方式,將當前傳送的message物件新增到佇列的尾部。實現資料的填充佇列處理。

looper.loop()的原始碼中可以看到,在程式啟動時,在主線程中loop()方法的for (;;)進行無限迴圈,通過message msg = queue.next()取得佇列中的首位message訊息物件,然後通過handler的msg.target.dispatchmessage(msg)進行分發處理。

public

void

dispatchmessage

(message msg)

else

}handlemessage

(msg);}

}

其中此時msg.callback為null,則進入

if

(mcallback != null)

}handlemessage

(msg)

;

然後在我們的activity中重寫

private handler handler1 =

newhandler

(new

handler.callback()

});

或者

private handler handler2 =

newhandler()

};

來進行主線程中處理資料更新。

子執行緒中handler1.post()或者runonuithread可以更新ui的原因

其中runonuithread方法為

public

final

void

runonuithread

(runnable action)

else

}

同樣呼叫handler的post方法。

然後進入

public

final

boolean

post

(runnable r)

呼叫sendmessagedelayed方法時,引數getpostmessage(r)為將post的runnable方法賦值給message。

private

static message getpostmessage

(runnable r)

其中message的callback屬性為runnable。然後同樣呼叫到enqueuemessage()方法中,然後通過主線程中loop.loop()的無限迴圈將其拿到,呼叫dispatchmessage方法,

public

void

dispatchmessage

(message msg)

else

}handlemessage

(msg);}

}

此時msg.callback將不為null,將會進入handlecallback(msg);中,執行

private

static

void

handlecallback

(message message)

run()方法進行主線程更新操作。

handler原始碼分析

昨天研究了一下handler的原始碼,今天總結一下 android只有乙個執行緒可以操作ui介面,我們稱之為ui執行緒。每個ui執行緒都維護乙個looper,這個looper中有乙個messagequeue來儲存ui乙個訊息佇列。通過控制這個訊息佇列來實現對ui介面的順序重新整理。handler.s...

Handler通訊 原始碼分析

1.messagequeue 訊息佇列 執行緒中更新 ui 的時候經常是呼叫 sendmessage 和 sendmessagedelayed 這樣 我跟蹤 進入到 handler 的 sendmessage 方法 public final boolean sendmessage message m...

Handler原始碼解析

意思就是說 在沒有呼叫looper.prepare 之前不能在子執行緒建立handler。為什麼在主線程中我們就已經可以直接建立handler?因為在activity的啟動 中,已經在當前ui執行緒 主線程 呼叫了looper.preparemainlooper 和looper.loop 方法。我們...