今天記錄我所掌握的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 訊...