看看Android Handler原始碼
趁著有時間,看看Android原始碼,先來看看Handler,後期的時候在更新吧。都忘記了上次看原始碼是什麼時候了。廢話不哆嗦了,先了解下Handler是幹嘛的,內容簡介啊,原理啊,裡面實現的方法啊,涉及到的設計模式啊,我進來滿足大家,給大家展示,至於寫個什麼樣的demo我還沒想好,不過網上很多了,可以自己去尋找尋找。開始搞起~
一.Handler 講什麼的?
每個Handler例項都與一個執行緒和該執行緒的訊息佇列相關聯。當您建立一個新的Handler時,它被繫結到建立它的執行緒/訊息佇列 ——從那開始,它將傳遞訊息傳送該訊息佇列中,並在訊息佇列結束時執行它們。
二.我們主要拿來幹嘛呢?
兩件事兒能幹:
1.排程訊息和程式碼,以便在將來的某個時間執行;
2.對要在不同於您自己的執行緒上執行的操作進行查詢;
三.簡單的畫了一個圖,理解一下Handler+Looper+Message+MessageQueue的工作原理
通俗來講:
1.建立一個Handler,然後Handler傳送一個訊息(Message)放在訊息佇列(MessageQueue)中。
2.通過Looper的死迴圈,然後不斷的從訊息佇列中去訊息,然後處理訊息。
3.處理完的訊息,通過Handler的handlerMessage或者是CallBack方法來回調給Handler。
這樣整個過程就完成了。
四. 我們看下Handler中提供的構造方法
1.public Handler()
預設建構函式將此處理程式與當前執行緒的Looper關聯。如果該執行緒沒有迴圈器,則此處理程式將無法接收訊息,因此會引發異常。
2.public Handler(Callback callback)
建構函式將此處理程式與當前執行緒的佇列關聯,並接受一個可在其中處理訊息的回撥介面。
3.public Handler(Looper looper)
使用提供的佇列而不是預設佇列。
4.public Handler(Looper looper, Callback callback)
使用提供的佇列而不是預設佇列,並進行回撥介面,在其中處理訊息。
五.看看裡面我們常用的幾個方法的實現;
1.handler的sendMessage()
/**
* Pushes a message onto the end of the message queue after all pending messages
* before the current time. It will be received in {@link #handleMessage},
* in the thread attached to this handler.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
sendMessage 裡面實現的是一個sendMessageDelayed,那我們繼續看看他的原始碼吧;
/**
* Enqueue a message into the message queue after all pending messages
* before (current time + delayMillis). You will receive it in
* {@link #handleMessage}, in the thread attached to this handler.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
其中的2個引數,一個是傳遞的訊息Message、 另外的是我們要執行的延遲時間;按照原始碼中的提示,接著看看下面的sendMessageAtTime方法;
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
啊哈,終於可以看到最終的實現了,簡單的分析一下:
先看看我們建立的MessageQueue中是否有未處理的訊息,之後要看的就是enqueueMessage方法的返回值來判斷是否成功。看看這個方法搞什麼呢?
在MessageQueue中的原始碼看到這個方法如下;
final boolean enqueueMessage(Message msg, long when) {
if (msg.when != 0) {
throw new AndroidRuntimeException(msg
+ " This message is already in use.");
}
if (msg.target == null && !mQuitAllowed) {
throw new RuntimeException("Main thread not allowed to quit");
}
synchronized (this) {
if (mQuiting) {
RuntimeException e = new RuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
return false;
} else if (msg.target == null) {
mQuiting = true;
}
msg.when = when;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
this.notify();
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
this.notify();
}
}
return true;
}
1.我們來看下if裡面的條件,如果mMessages物件為空,或者when為0也就是立刻執行,或者新訊息的when時間比mMessages佇列的when時間還要早,符合以上一個條件就把新的msg插到mMessages的前面 並把next指向它,也就是msg會插進上圖中佇列的最前面,等待loop的輪詢。
2.如果上面的條件都不符合就進入else程式碼中,我們可以看到17行是有個for的死迴圈遍歷已有的message物件,其中第20行中有個if語句when < p.when when是新訊息的執行時間,p.when的是佇列中message訊息的執行時間,如果找到比新的message還要晚執行的訊息,就執行 msg.next = p; prev.next = msg; 也就是把插到該訊息的前面,優先執行新的訊息。
其實Handler總結到這裡,我也不知道該說什麼了,簡單的分享一個demo,大家都會的,也讓大家理解一下Handler的應用吧,實現一個倒計時功能;哈哈哈
eg:
在MainActivity中建立一個Handler,然後實現倒計時。程式碼如下:
private static int TIME = 5;
private TextView mTime;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
TIME--;
mTime.setText(TIME + "s");
if (TIME > 0) {
Message message = handler.obtainMessage(1);
handler.sendMessageDelayed(message, 1000);
}
}
super.handleMessage(msg);
}
};
學習的時光總是要花費的,希望大家喜歡我的分享;我的公眾號也可以關注哦。掃碼下面的二維碼即可;