與handler共同作用的有looper,messagequeue,message。我麼接下來從原始碼的角度看看整個過程的大概實現。首先說一下每個物件的作用:
looper:訊息輪詢循器,不斷的從訊息佇列中取出訊息交給handler處理
messagequeue:訊息佇列,用於儲存從handler傳送過來的訊息
message:訊息物件,可以攜帶資料
handler:用於傳送和處理訊息
在android中,主線程預設已經建立了looper和messagequeue物件,我們去分析一下。
activitythread代表了主線程物件,它的main方法是應用程式的入口,在main方法中建立了looper。
我們看看preparemainlooper的實現looper.preparemainlooper();
activitythread thread
=new activitythread();
looper.
loop();
呼叫了帶引數的prepare方法public
static
void
preparemainlooper()
smainlooper = mylooper();
}}
我們看看looper的構造方法private
static
void
prepare(boolean quitallowed)
//將looper儲存在threadlocal中
sthreadlocal.set(new looper(quitallowed));
}
最後是mylooper()方法private
looper(boolean quitallowed)
threadlocal有什麼作用呢?下面大概介紹一下public
static @nullable looper mylooper()
threadlocal是乙個執行緒內部的資料儲存類,通過它可以在指定的執行緒中儲存資料,資料儲存以後,只有在指定執行緒中可以獲取到儲存的資料,對於其它執行緒來說無法獲取到資料,threadlocal可以在不同的執行緒之中互不干擾地儲存並提供資料,通過threadlocal可以輕鬆獲取每個執行緒的looper。
總結:looper.preparemainlooper()方法做了三件事
接下來我們看看這個msg.target是如何被賦值的,這就要從傳送訊息的過程開始分析。首先需要建立handler物件public static void
loop()
//取出looper對應的訊息佇列,訊息佇列是在looper的建構函式中建立的
final messagequeue queue
= me.mqueue;
......//死迴圈,可能阻塞,作用是不斷從訊息佇列取訊息
for (;;)
......//呼叫訊息物件的target的dispatchmessage方法分發訊息
//其實這個target是handler物件,後面我們會看到
msg.target.dispatchmessage(msg);
...... }
}
public
handler()
有了handler物件,我們開始傳送訊息,我們一般採用下面的方式傳送訊息public
handler(callback callback, boolean async)
}mlooper = looper.mylooper();
if (mlooper == null)
//將looper中的訊息佇列與當前handler關聯
mqueue = mlooper.mqueue;
mcallback = callback;
masynchronous = async;
}
我們繼續跟進原始碼public
final
boolean
sendemptymessage(int what)
public
final
boolean
sendemptymessagedelayed(int what, long delaymillis)
繼續往下看public
final
boolean
sendmessagedelayed(message msg, long delaymillis)
return sendmessageattime(msg, systemclock.uptimemillis() + delaymillis);
}
接下類看看enqueuemessage方法public
boolean
sendmessageattime(message msg, long uptimemillis)
return enqueuemessage(queue, msg, uptimemillis);
}
在enqueuemessage方法中,我們終於證實了msg.target是乙個handler物件,接下來呼叫了訊息佇列的enqueuemessage方法private
boolean
enqueuemessage(messagequeue queue, message msg, long uptimemillis)
return queue.enqueuemessage(msg, uptimemillis);
}
最後我們就要知道訊息是在何時被處理的,也就是說handlemessage方法在何處被呼叫的,我們知道,在looper的loop()方法中呼叫了下面的**//此方法的作用是將訊息插入到訊息佇列中,訊息佇列是線性鍊錶結構
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所關聯的handler物件的dispatchmessage方法msg.target
.dispatchmessage(msg);
看到了吧,終於發現了handlemessage方法的呼叫。public
void
dispatchmessage(message msg) else
}handlemessage(msg);
}}
用到handler,需要對比一下近似方法:
a.activity,runonuithread(runnnable)
view.post
view.postdelayed
b.handler類
c.asynctask
這三種方法實際上都是基於handler類演變而來,只是表現形式不一樣,比如asynctask是對handler和thread的乙個封裝。三種方式區別
從原始碼的角度理解Volley
今天從原始碼的角度來理解一下volley中部分功能的實現。新增請求到請求佇列 將請求新增到請求佇列中 public requestadd requestrequest 為請求設定順序編號.request.setsequence getsequencenumber 新增標記 request.addma...
從原始碼角度來看UVM phase
說到uvm phase我們就知道是uvm乙個很重要的特性,從使用者角度來講,其實就是一些很簡單的應用規則,能夠極大地提公升編碼的效率,簡化 複雜度,提高debug的效率。至於應用可以參看zhangqiang大佬的第五章,這裡就不再贅述。本文就從原始碼的角度來看,uvm的phase是怎麼工作的?之前學...
從原始碼角度分析RACObserve的實現原理(一)
racobserve是個巨集,racobserve target,keypath 最終是執行 target rac valuesforkeypath keypath target,keypath observer self 這就牽出nsobject racpropertysubscribing ca...