Handler 介紹
Handler 允許你發送和處理與執行緒的 MessageQueue 關聯的 Message 和 Runnable 物件,每個 Handler 實體都與一個執行緒和該執行緒的訊息佇列相關聯,當你創建一個新的 Handler 時,它會系結到一個 Looper,它會將訊息和可運行物件傳遞到該 Looper 的訊息佇列,并在該 Looper 的執行緒上執行它們,
Handler 有兩個主要用途:
-
1、安排訊息和可運行物件在將來的某個時間執行;
-
2、將要在與您自己的執行緒不同的執行緒上執行的操作排入佇列,
主要場景是子執行緒完成耗時操作的程序中,通過 Handler 向主執行緒發送訊息 Message,用來重繪 UI 界面, 本文咱們來了解 Handler 的發送訊息和處理訊息的原始碼實作,
分析原始碼的時候最好是找到一個合適的切入點,Handler 原始碼的一個切入點就是它的默認構造器,
分析原始碼
new Handler()
public Handler() {
this(null, false);
}
public Handler(@Nullable Callback callback, boolean async) {
//發現泄露,初始值false,不看往下走
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//注釋1
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
//注釋2
mQueue = mLooper.mQueue;
//null
mCallback = callback;
//false
mAsynchronous = async;
}
在無參構造器里呼叫了多載的構造方法并分別傳入 null 和 false,并且在構造方法中給兩個全域變數賦值:mLooper 和 mQueue,mLooper是通過 Looper 來獲取,mQueue 是通過 mLooper.mQueue 獲取,這說明他們都來找于 Looper ,咱們先看myLooper吧,
Looper.myLooper()
final MessageQueue mQueue;
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
sThreadLocal.get()
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();
}
可以看出,myLooper 通過一個執行緒本地變數中的存根,然后 mQueue 是 Looper 中的一個全域變數,型別是 MessageQueue 型別,
MessageQueue:保存要由 Looper 調度的訊息串列, Message不是直接添加到 MessageQueue 的,而是通過與 Looper 關聯的 Handler 物件添加的,你可以使用 Looper.myQueue() 檢索當前執行緒的 MessageQueue,
Looper 介紹
默認情況下,執行緒沒有與之關聯的訊息回圈;要創建一個,在運行回圈的執行緒中呼叫 prepare ,然后回圈讓它處理訊息,直到回圈停止,
大多數與訊息回圈的互動是通過 Handler 類進行的,
這是一個Looper執行緒實作的典型例子,利用prepare和loop的分離,創建了一個初始Handler與Looper進行通信,
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler(Looper.myLooper()) {
public void handleMessage(Message msg) {
// 在這里處理傳入的訊息
}
};
Looper.loop();
}
}
啟動一個 java 程式的入口函式是 main 方法,但是當 main 函式執行完畢之后此程式停止運行,也就是行程會自動終止,
但是當我們打開一個 Activity 之后,只要我們不按下回傳鍵 Activity 會一直顯示在螢屏上,也就是 Activity 所在行程會一直處于運行狀態,實際上 Looper 內部維護一個無限回圈,保證 App 行程持續進行,
Looper初始化
Activity.attach() 方法中會傳入一個ActivityThread,ActivityThread 的 main 方法是一個新的 App 行程的入口,
ActivityThread.main()
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
// 安裝選擇性系統呼叫攔截
AndroidOs.install();
// 禁止CloseGuard
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
//確保 TrustedCertificateStore 查找 CA 證書的正確位置
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
// 呼叫每個行程的主線模塊初始化,
initializeMainlineModules();
Process.setArgV0("<pre-initialized>");
//重點:注釋1
//初始化當前行程的 Looper 物件
Looper.prepareMainLooper();
...
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
...
//重點:注釋2
//呼叫 Looper 的 loop 方法開啟無限回圈,
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
注釋1:就初始化當前行程的 Looper 物件;
注釋2:呼叫 Looper 的 loop 方法開啟無限回圈(具體下面講到),
Looper.prepareMainLooper()
public static void prepareMainLooper() {
//注釋1:創建一個Looper
//下面把方法貼出來
prepare(false);
//加個同步方法物件鎖
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
//這個要等prepare執行完再看
//注釋1
sMainLooper = myLooper();
}
}
Looper.prepare()
private static void prepare(boolean quitAllowed) {
//判斷是否系結過 Looper 物件
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
Looper.prepare 方法其實就是new 一個 Looper,核心之處在于將 new 出的 Looper 設定到了執行緒本地變數 sThreadLocal.set(looper) 中,也就是說創建的 Looper 與當前執行緒發生了系結,
注意:在創建 Looper 物件之前,會判斷 sThreaLocal 中是否已經系結過 Looper 物件,如果是則拋出例外,這行代碼的目的是確保在一個執行緒中 Looper.prepare() 方法只能被呼叫 1 次,
new Looper()
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
Looper在構造方法中初始化了訊息佇列 MessageQueue 物件,
prepare 方法執行完之后,會在 Looper.prepareMainLooper 中處呼叫 myLooper() 方法,從 sThreadLocal 中取出 Looper 物件并賦值給 sMainLooper 變數,
Looper.prepare() 只能被呼叫1次
從上面代碼可以看出Activity在被創建時已經在 Looper.prepareMainLooper()中呼叫了一次Looper.prepare(),我決定在onCreate()里面再呼叫一次Looper.prepare(),祝福我吧, 我現在我準備在MainActivity中加一行代碼
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Looper.prepare();
}
結果慘兮兮:

注意:
prepare 方法在一個執行緒中只能被呼叫 1 次;
Looper 的構造方法在一個執行緒中只能被呼叫 1 次;
MessageQueue 在一個執行緒中只會被初始化 1 次,
結論:也就是說 UI 執行緒中只會存在 1 個 MessageQueue 物件,后續我們通過 Handler 發送的訊息都會被發送到這個 MessageQueue 中,
Looper 干啥的?
總結 Looper 做的事情就是:不斷從 MessageQueue 中取出 Message,然后處理 Message 中指定的任務,
回到原點,在 ActivityThread 的 main 方法中,除了呼叫 Looper.prepareMainLooper 初始化 Looper 物件之外,還呼叫了 Looper.loop 方法開啟無限回圈,Looper 的主要功能就是在這個回圈中完成的,
Looper.loop()
public static void loop() {
//取出 Looper 物件并賦值給 me
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
if (me.mInLoop) {
Slog.w(TAG, "Loop again would have the queued messages be executed"
+ " before this one completed.");
}
me.mInLoop = true;
final MessageQueue queue = me.mQueue;
...
//下面這個死回圈,進去就甭想出來了,
for (;;) {
//注釋1
//呼叫 MessageQueue 的 next 方法取出 Message
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...
try {
//注釋2
//msg不為null,進行處理
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} catch (Exception exception) {
if (observer != null) {
observer.dispatchingThrewException(token, msg, exception);
}
throw exception;
} finally {
ThreadLocalWorkSource.restore(origWorkSource);
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
...
msg.recycleUnchecked();
}
}
上面代碼表示 loop 方法中執行了一個死回圈,這也是一個 Android App 行程能夠持續運行的原因,
注釋1:不斷地呼叫 MessageQueue 的 next 方法取出 Message,
注釋2:如果 message 不為 null,則處進行后續處理,具體就是從 Message 中取出 target 物件,然后呼叫其 dispatchMessage 方法處理 Message 自身,target是誰?
Message.target
public final class Message implements Parcelable {
...
@UnsupportedAppUsage
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public long when;
/*package*/ Bundle data;
@UnsupportedAppUsage
/*package*/ Handler target;
@UnsupportedAppUsage
/*package*/ Runnable callback;
// sometimes we store linked lists of these things
@UnsupportedAppUsage
/*package*/ Message next;
/** @hide */
public static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
...
}
查看后其實就是個Handler,那咱們再看看Handler 的 dispatchMessage 方法
Handler.dispatchMessage()
/**
* Handle system messages here.
* 在這里處理系統訊息,
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
/**
* Subclasses must implement this to receive messages.
* 子類必須實作它才能接收訊息,
*/
public void handleMessage(@NonNull Message msg) {
}
可以看出,在 dispatchMessage 方法中會呼叫一個空方法 handleMessage,而這個方法也正是我們創建 Handler 時需要覆寫的方法,那么 Handler 是何時將其設定為一個 Message 的 target 的呢?
Handler.sendMessage()
Handler 有幾個多載的 sendMessage 方法,但是基本都大同小異,咱使用最普通的 sendMessage 方法來分析,代碼具體如下:
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
Handler.sendMessageDelayed()
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
Handler.sendMessageAtTime()
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);
}
經過幾層呼叫之后,在這里我們拿到了在 ActivityThread 的 main 方法中通過 Looper 創建的 MessageQueue,
并且最后呼叫 enqueueMessage 方法將 Message 插入到訊息佇列 MessageQueue 中,
Handler.emqueueMessage()
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
//注釋
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
注釋:將 Handler 自身設定為 Message的target(Handler) 物件,下來咱們看看 MessageQueue 的 enqueueMessage 方法,因此后續 Message 會呼叫此 Handler 的 dispatchMessage 方法來處理,
MessageQueue.enqueueMessage()
boolean enqueueMessage(Message msg, long when) {
//注釋1,非空判斷
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
synchronized (this) {
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
//注釋2,從這朝下都蠻重要的
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
注釋1:會判斷msg.target == null 沒有設定,則直接拋出例外;
注釋2:會按照 Message 的時間 when 來有序得插入 MessageQueue 中,可以看出 MessageQueue 實際上是一個有序佇列,只不過是按照 Message 的執行時間來排序,
后續就是通過 ActivityThread 的 main 方法中 Looper 創建的 MessageQueue,Looper 從 MessageQueue 中取出 Message 之后,會呼叫 dispatchMessage 方法進行處理,
至此 Handler 的發送訊息和訊息處理流程已經介紹完畢,
重點關注
Handler 的 post(Runnable) 與 sendMessage(Message msg) 有什么區別
樣例:
public class HandlerActivity extends ActivityBase{
ActivityHandlerBinding binding ;
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(@NonNull Message msg) {
switch (msg.what){
case 1:
binding.tvTotle.setText(String.format("哈哈哈哈考了%d",msg.arg1));
break;
}
return false;
}
});
@Override
protected void onCreate(@Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityHandlerBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.btnSendMessage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Message msg = new Message();
msg.what=1;
msg.arg1=100;
handler.sendMessage(msg);
}
});
binding.btnPost.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.post(new Runnable() {
@Override
public void run() {
binding.tvTotle.setText(String.format("哈哈哈哈考了%d",80));
}
});
}
});
}
}
Handler.post()
public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
然后呼叫 getPostMessage() 傳入 Runnable ,咱看看這個是干嘛的?
Handler.getPostMessage()
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
在這個方法中你會發現getPostMessage()會將 Runnable 賦值到 Message 的 callback 變數中,回傳一個Message,并呼叫 sendMessageDelayed 方法,
Handler.sendMessage()
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
對比發現他們都呼叫 sendMessageDelayed() ,只不過生成的Message方式不同, sendMessageDelayed() 上文已經講到了就不多描述了,可以向上翻翻,
可以看出,經過幾層呼叫之后,sendMessageDelayed() 最侄訓呼叫 enqueueMessage() 方法將 Message 插入到訊息佇列 MessageQueue 中,而這個訊息佇列就是我們剛才分析的在 ActivityThread 的 main 方法中通過 Looper 創建的 MessageQueue,
Looper 通過 loop() 方法從 MessageQueue 中取出 Message ,Message.target(Handrle) 會呼叫 dispatchMessage 方法進行處理,下面咱再看看它的原始碼,
Handrle.dispatchMessage()
/**
* Handle system messages here.
* 在這里處理系統訊息,
*/
public void dispatchMessage(@NonNull Message msg) {
//注釋1
if (msg.callback != null) {
handleCallback(msg);
} else {
//注釋2
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
咱先看看handleCallback方法
Handrle.handleCallback()
private static void handleCallback(Message message) {
message.callback.run();
}
很明顯,dispatchMessage 分兩種情況:
注釋1:msg.callback != null,一般為通過 post(Runnabl) 方式,會直接執行 Runnable 的 run 方法,因此這里的 Runnable 實際上就是一個回呼介面,跟執行緒 Thread 沒有任何關系,
注釋2:msg.callback == null,這種一般為 sendMessage 的方式,則會呼叫 Handler 的 hanlerMessage 方法進行處理,
Looper.loop() 為什么不會阻塞主執行緒
剛才我們了解了,Looper 中的 loop 方法實際上是一個死回圈,但是我們的 UI 執行緒卻并沒有被阻塞,反而還能夠進行各種手勢操作,這是為什么呢?在 MessageQueue 的 next 方法中.
MessageQueue.next()
Message next() {
// mPtr :used by native code
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
//-1:僅在第一次迭代期間
int pendingIdleHandlerCount = -1;
//下一個Poll超時時間
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
//將當前執行緒中掛起的所有 Binder 命令重繪到內核驅動程式,
//在執行可能會阻塞很長時間的操作之前呼叫這會很有用,
//以確保任何掛起的物件參考都已被釋放,以防止行程持有物件的時間超過它所需的時間,
Binder.flushPendingCommands();
}
//注釋:重點來了,
nativePollOnce(ptr, nextPollTimeoutMillis);
...
}
}
MessageQueue.nativePollOnce()
/*non-static for callbacks*/
private native void nativePollOnce(long ptr, int timeoutMillis);
nativePollOnce 方法是一個 native 方法,當呼叫此 native 方法時,主執行緒會釋放 CPU 資源進入休眠狀態,直到下條訊息到達或者有事務發生,通過往 pipe 管道寫端寫入資料來喚醒主執行緒作業,這里采用的 epoll 機制,下面是關于 nativePollOnce 的部分分析,參考了nativePollOnce函式分析,感興趣的可以去自己看看,有點懵,等我再努力努力再來看這些吧,
epoll機制:提供了Linux平臺上最高效的I/O復用機制, 從呼叫方法上看,epoll的用法和select/poll非常類似,其主要作用就是I/O復用,即在一個地方等待多個檔案句柄的I/O事件,
nativePollOnce的實作函式是android_os_MessageQueue_nativePollOnce,
android_os_MessageQueue_nativePollOnce
frameworks/base/core/jni/android_os_MessageQueue.cpp
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
jlong ptr, jint timeoutMillis) {
NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
//取出NativeMessageQueue物件,并呼叫它的pollOnce
nativeMessageQueue->pollOnce(env, obj, timeoutMillis);
}
pollOnce()
frameworks/base/core/jni/android_os_MessageQueue.cpp
void NativeMessageQueue::pollOnce(JNIEnv* env, jobject pollObj, int timeoutMillis) {
mPollEnv = env;
mPollObj = pollObj;
//重任傳遞到Looper的pollOnce函式
mLooper->pollOnce(timeoutMillis);
mPollObj = NULL;
mPollEnv = NULL;
if (mExceptionObj) {
env->Throw(mExceptionObj);
env->DeleteLocalRef(mExceptionObj);
mExceptionObj = NULL;
}
}
pollOnce()
system/core/libutils/include/utils/Looper.h
/**
* 等待事件可用,以毫秒為單位可選超時,
* 為發生事件的所有檔案描述符呼叫回呼,
* 如果超時為零,則立即回傳而不阻塞,
* 如果超時為負,則無限期等待直到事件出現,
* 如果之前使用wake() 喚醒輪詢,則回傳POLL_WAKE
* 超時到期,沒有呼叫回呼,也沒有其他檔案
* 描述符已準備就緒,
* 如果呼叫了一個或多個回呼,則回傳 POLL_CALLBACK,
* 如果在給定之前沒有資料等待超時,則回傳 POLL_TIMEOUT,
* 如果等待程序中發生錯誤,則回傳 POLL_ERROR,
* 如果檔案描述符有資料,則回傳一個 >= 0 包含識別符號的值
* 并且它沒有回呼函式(這里需要呼叫者來處理它),
* 在這個(并且只有這個)情況下,outFd、outEvents 和 outData 將包含投票
* 與 fd 關聯的事件和資料,否則它們將被設定為 NULL,
*
* 此方法在完成呼叫適當的回呼之前不會回傳
* 用于所有已發出信號的檔案描述符,
*/
int pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData);
inline int pollOnce(int timeoutMillis) {
//timeOutMillis引數為超時等待時間,如果為-1,則表示無限等待,直到有事件發生為止,如果值為0,則無需等待立即回傳,
return pollOnce(timeoutMillis, nullptr, nullptr, nullptr);
}
pollOnce()
system/core/libutils/Looper.cpp
int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
int result = 0;
//一個無限回圈
for (;;) {
//mResponses是一個Vector,這里首先需要處理response
while (mResponseIndex < mResponses.size()) {
const Response& response = mResponses.itemAt(mResponseIndex++);
int ident = response.request.ident;
if (ident >= 0) {
//首先處理那些沒有callback的Response
int fd = response.request.fd;
int events = response.events;
void* data = response.request.data;
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ pollOnce - returning signalled identifier %d: "
"fd=%d, events=0x%x, data=%p",
this, ident, fd, events, data);
#endif
if (outFd != nullptr) *outFd = fd;
if (outEvents != nullptr) *outEvents = events;
if (outData != nullptr) *outData = data;
//實際上,對于沒有callback的Response,pollOnce只是回傳它的ident,
//并沒有實際做什么處理,因為沒有callback,所以系統也不知道如何處理
return ident;
}
}
if (result != 0) {
#if DEBUG_POLL_AND_WAKE
ALOGD("%p ~ pollOnce - returning result %d", this, result);
#endif
if (outFd != nullptr) *outFd = 0;
if (outEvents != nullptr) *outEvents = 0;
if (outData != nullptr) *outData = nullptr;
return result;
}
//呼叫pollInner函式,注意,它在for回圈內部
result = pollInner(timeoutMillis);
}
}
Handler 的 sendMessageDelayed 或者 postDelayed 是如何實作的
上面說到,在向 MessageQueue 佇列中插入 Message 時,會根據 Message 的執行時間排序,而訊息的延時處理的核心實作是在獲取 Message 的階段,接下來看下 MessageQueue 的 next 方法,
MessageQueue.next()
Message next() {
...
for (;;) {
...
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// 嘗試檢索下一條訊息, 找到就回傳,
//獲取系統時間,
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null) {
if (now < msg.when) {
// 下一條訊息未準備好, 設定超時以在準備好時喚醒,
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// 收到一條訊息,
//mBlocked:指示 next() 是否在 pollOnce() 中以非零超時阻塞等待,
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
//回傳 Message
return msg;
}
} else {
// 沒有更多的訊息,
nextPollTimeoutMillis = -1;
}
}
}
}
上面表示從 MessageQueue 中取出一個 Message,但是當前的系統時間小于 Message.when,因此會計算一個 timeout,目的是實作在 timeout 時間段后再將 UI 執行緒喚醒,因此后續處理 Message 的代碼只會在 timeout 時間之后才會被 CPU 執行,
注意:在上述代碼中也能看出,如果當前系統時間大于或等于 Message.when,那么會回傳 Message 給 Looper.loop(),但是這個邏輯只能保證在 when 之前訊息不被處理,不能夠保證一定在 when 時被處理,
總結

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/299369.html
標籤:其他
上一篇:猿代碼軟體培訓 | 哪些高校畢業生有機會進華為?(名單)
下一篇:Android——自定義View
