安卓原始碼學習之Handler執行流程

2021-07-02 14:39:37 字數 3377 閱讀 9699

今天記錄我所掌握的handler訊息機制執行流程,平時我們都會使用到handler物件來進行延遲訊息的處理或者結合執行緒來更新ui控制項,但是對裡面的原理也不是很了解,所以我今天看了一下原始碼,把看到的東西記錄下來。

首先我們使用handler肯定的new乙個它的物件,那new的過程當中它都做了些什麼事呢?於是乎我開啟了原始碼:

//這裡是它的午餐構造方法,它總共有幾個構造方法,最終都是呼叫的這個構造

//方法下面的構造方法

public

handler()

//最終呼叫的是這個構造方法

public

handler(callback callback, boolean async)

mqueue = mlooper.mqueue;//獲取訊息佇列

mcallback = callback;

masynchronous = async;

}

當然,獲取到handler物件以後肯定是要使用它的,我們通過呼叫它的sendmessage(msg)方法或者其他send***方法來傳送訊息,於是乎我們得有乙個訊息物件啊,我們可以這麼做:

message msg=new message()或者message msg=handler.obtainmessage();大家都知道下面這個方法效率更加高,這是為什麼呢請看原始碼:

public

final message obtainmessage()

//最終handler.obtinmessage()會呼叫message物件的這個方法:

public

static message obtain()

}return

new message();

}//從上面可以看到,如果使用obtinmessage()方法會先往訊息池裡面取出,如果去不到則例項化乙個返回,這就是為什麼obtinmessage比newmessage效率高的原因!

好了,獲取到message物件以後肯定得傳送訊息啊,於是我們跟蹤一下handler.sendmessage(message msg)方法原始碼:

public

final

boolean

sendmessage(message msg)

public

final

boolean

sendmessagedelayed(message msg, long delaymillis)

return sendmessageattime(msg, systemclock.uptimemillis() + delaymillis);

}//最終呼叫了這個方法

public

boolean

sendmessageattime(message msg, long uptimemillis)

可以看到傳送訊息最終會呼叫enqueuemessage(queue, msg, uptimemillis)方法,我們進入這個方法一看究竟:

private

boolean

enqueuemessage(messagequeue queue, message msg, long uptimemillis)

根據messagequeue的enqueuemessage方法:

boolean enqueuemessage(message msg, long 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;

}//從上面的**可以分析出如果出入的延遲時間為0則優先順序最高

//這裡是從訊息佇列中取出訊息以後底層呼叫的方法,好像從這裡以後這個方法是系

//底層呼叫的,查了一下資料貌似是乙個linux管道設定的方法

public

void

dispatchmessage(message msg) else

}//這裡呼叫了handlemessage方法

handlemessage(msg);}}

//於是呼叫了傳送訊息以後就會呼叫handlermessage(message msg)方法進行我們自己的**處理了。

具體的流程圖可以用如下圖來表示:

引入上面我提出的問題,就是在handler的無參構造方法裡:

public

handler(callback callback, boolean async)

mqueue = mlooper.mqueue;//獲取訊息佇列

mcallback = callback;

masynchronous = async;

}

我提出的為什麼looper.mylooper();可能獲取的looper物件為空?首先想一下我們有時候在子執行緒中建立handler物件的時候會發生什麼情況呢?當然是報錯了,這個報錯的資訊就是上面原始碼中的提示資訊:」can』t create handler inside thread that has not called looper.prepare()」,那為什麼主線程中new 乙個handler物件就不會報錯呢?那是因為在主線程建立的時候系統就會跟著建立乙個looper物件,而子執行緒中不會主動建立looper物件,當我們在子執行緒中先這樣寫:

looper.prepare();

....

looper.loop();

就不會報錯了,這裡貼出主線程建立looper物件的原始碼:

public

static

void

main(string args)

asynctask.init();

if (false)

looper.loop();//迴圈取出訊息

所以我們在主線程中new handler不會報錯,在子執行緒中需要加上looper.prepare()和looper.loop()方法的原因了。

具體的流程就分析完畢,如果不對的地方麻煩看的朋友指出一下,我寫部落格是為了把自己學習的東西記錄下來,同時鍛鍊一下自己的表達能力,希望如果有不對的地方麻煩老師指點一下,謝謝!

安卓原始碼閱讀 原始碼編譯

mkdir bin path bin path curl bin repo chmod a x bin repowget tsinghua edu cn aosp monthly aosp latest.tar tar xf aosp latest.tar cd aosp 解壓得到的 aosp 工程...

安卓原始碼的結構

linux提供給android系統的核心系統服務包括安全,記憶體管理,程序管理,網路組合驅動模型等內容。android源 的全部工程分為三個部分 core project 核心工程部分,這是建立android系統的基礎,儲存在根目錄的各個資料夾中。external project 擴充套件工程部分,...

安卓的handler機制

一 定義 handler是訊息處理的機制,很多耗時的操作,如訪問網路 i o操作等不能在主線程中執行,而這些操作又與ui的變化相關聯。常常採用由子執行緒完成操作,傳送訊息使切換到主線程更新ui的辦法。當然也可以用來獲取資料等。與handle相關的類 message 訊息 messagequeue 訊...