Runnable 基本上也是 Message, 當調用 postDelayed() 調度某個 Runnable 的時候, 會將其包裝成一個 Message,然後再使用 sendMessageDelayed()這個方法進行發送 。不論是 post() 還是 send() 這類的方法,他們最後都是經過 Handler 的 sendMessageAtTime() 方法來加入到 MessageQueue , 最終經 由 發送他們的 Handler 做處理。
Handler 的源碼 , 當 Handler 透過 postDelayed() 調度某個 Runnable , 其實還是被包裝成 Message 經由 sendMessageDelayed 這個方法進行發送
public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
如下:由下我們可以得知 , 不論是 sendEmptyMessage , sendEmptyMessageDelayed 抑或是sendMessageDelayed , 最終都會導到 sendMessageAtTime() 方法來將 Message 加入到 MessageQueue
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
sendMessageAtTime() 方法 會執行 enqueueMessage()
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
上一篇有提到 Message 會關聯 送出他的 Handler , 當 輪到這個 Message , Looper會把它取出 , 送出它的 Handler 會把它處理掉。looper 拿到 Message 後 透過 msg.target 找到了當初送出他的 Handler ,這 Handler 會利用 dispatchMessage 將 Message 處理掉。
Handler 處理訊息的路徑有三
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
// 1.
if (msg.callback != null) {
handleCallback(msg);
} else {
// 2.
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
// 3.
handleMessage(msg);
}
}
handleCallback 方法
private static void handleCallback(Message message) {
message.callback.run();
}
Handler 內的 handleMessage 方法
public void handleMessage(Message msg) {
}
今天只要實例化一個 Handler() , 我們會走上述第二條路 , 不傳 callback 給 Handler
handler = Handler()
dispatchMessage() 方法中 在處理 第二條路的 Message , 會調用 handleCallback ()
Runnable 的 run 方法會得到 回調。 在 run 方法 執行我們想執行的程式碼。
下面在 run() 方法內 , handler.postDelayed(runnable,1000) 這一行 , 我們又送出了 Message , 這行
是今天實作的重點。在處理完Message之後 又再送出 Message , 此時會變成一個循環。
runnable = object :Runnable{
override fun run() {
currentms++
setCurrentTime()
handler.postDelayed(runnable,1000)
}
}
postDelayed 方法 需傳入的兩個參數 第一個 是這個 Runnable , 第二個是 Delay 幾秒才送出訊息
Handler 透過 postDelayed 將 Runnable 包裝成 Message 送出 , 開始計時。
Runnable 的 run 方法會獲得 回調 時 , Handler 在調用 同樣的方法 ,送出 Message 。
handler.postDelayed(runnable,1000)
當我們按下 停止按鈕時 , 調用 removeCallbacks()去移除 MessageQueue 上 runnable 包裝成的 Message , 此時 run 方法不再獲得回調 , 停止計時
handler.removeCallbacks(runnable)
今天 實作的 Timer 透過 postDelayed , 延遲 1 s 才執行 增加一秒 , 如果 post () 就沒有時間間隔了
Timer 透過 postDelayed , 過了 1 s 之後 , 變數自動 加 1 , 這樣實作 出計時的功能
currentms++
https://github.com/liyiwin/Day4_Timer