原理
Handler 通過post视事、send等發(fā)送消息時(shí)城瞎,會(huì)將消息插入到MessageQueue竖共,Looper的loop方法循環(huán)從MessageQueue里讀取消息苗胀,并交給Handler.dispatchMessage處理,由于Looper是以線程為作用域(以ThreadLocal保存)享潜,因此Looper調(diào)用Handler.dispatchMessage是切換到生成生成handler時(shí)的線程困鸥。
ThreadLocal
數(shù)據(jù)是以線程為作用域,不同線程具有不同的數(shù)據(jù)副本剑按∥迅铮可以在多個(gè)線程中互不干擾地存儲(chǔ)和修改數(shù)據(jù)。
private ThreadLocal<Boolean> mThreadLocal = new ThreadLocal<Boolean>();
public void main(){
mThreadLocal.set(true);
new Thread(new Runnable() {
@Override
public void run() {
mThreadLocal.set(false);
mThreadLocal.get(); //子線程為false
}
}).start();
mThreadLocal.get(); //主線程仍為true
}
原理
- 在Thread類的內(nèi)部有一個(gè)成員專門用于存儲(chǔ)線程的ThreadLocal.ThreadLocalMap
此map以ThreadLocal 作為鍵吕座,以具體數(shù)據(jù)做為value
ThreadLocal.ThreadLocalMap threadLocals = null;
- ThreadLocal get\set時(shí)先獲取當(dāng)前Thread的threadLocals虐译,再從threadLocals這個(gè)Map中取當(dāng)前ThreadLocal對象作為鍵對應(yīng)的值。
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
- 如果threadLocals為null吴趴,則調(diào)用setInitialValue方法初始化漆诽,以initialValue()返回值做為value
MessageQueue 消息隊(duì)列
- 內(nèi)部存儲(chǔ)消息列表,以隊(duì)列形式提供插入锣枝、刪除操作
- 實(shí)現(xiàn)不是真正的隊(duì)列厢拭,而是Message的單鏈表結(jié)構(gòu)
主要方法
- enqueueMessage插入消息
- next,讀取消息并刪除撇叁,是一個(gè)無限循環(huán)的方法供鸠,如果消息隊(duì)列中沒有消息,那么next方法會(huì)一直阻塞在這里陨闹。當(dāng)有新消息到來時(shí)楞捂,next方法會(huì)返回這條消息并將其從單鏈表中移除
Looper
不停從MessageQueue中查看是否有新消息,如果有新消息就會(huì)立刻處理趋厉,否則就一直阻塞在那里
主要方法
- Looper.preare()方法創(chuàng)建當(dāng)前線程的Looper
- Looper.loop()來開啟消息循環(huán).loop是一個(gè)死循環(huán)寨闹,調(diào)用MessageQueue的next方法取出消息。唯一跳出循環(huán)的方式是MessageQueue的next方法返回了null君账。只有當(dāng)MessageQueue被標(biāo)記為退出狀態(tài)時(shí)next才會(huì)返回null
- Loop.quit(),調(diào)用MessageQueue的quit或者quitSafely方法來通知消息隊(duì)列退出
Handler
Handler 負(fù)責(zé)消息的發(fā)送和接收繁堡。
Handler的工作需要Looper,沒有Looper的線程就會(huì)報(bào)錯(cuò)
消息發(fā)送
Handler發(fā)送消息的過程僅僅是向消息隊(duì)列中插入了一條消息
post\send等系列方法
消息接收處理 dispatchMessage
- 如果消息本身有callback 直接調(diào)用handlerCallback方法處理,完成
- 如果Handler.mCallback非空椭蹄,調(diào)用mCallback.handleMessage處理闻牡,返回true時(shí)完成
- 如果Handler.mCallback為空,或者非空但第2部返回false時(shí)绳矩,調(diào)用handleMessage處理罩润。
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}