Handler發(fā)消息,最終調(diào)用enqueueMessage方法調(diào)用MessageQueued對(duì)象摸航,MessageQueue的enqueueMessage方法的是做對(duì)象鎖的同步操作匙监,next方法也是做了對(duì)象鎖的同步操作担锤,MessageQueue內(nèi)部有個(gè)mMessages(Message)對(duì)象不翩,這2個(gè)方法都是操作這個(gè)msg對(duì)象齿诞,所以線程是安全衡便,enqueueMessage是負(fù)責(zé)把消息存在message献起,next是負(fù)責(zé)把消息返回給Looper
enqueueMessage方法的部分代碼
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
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 {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
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;
}
next方法的部分代碼
next方法:
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// Next message is not ready. Set a timeout to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (false) Log.v("MessageQueue", "Returning message: " + msg);
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis = -1;
}
在Looper的loop方法通過for循環(huán)調(diào)用MessageQueue的next,獲取隊(duì)列的消息镣陕,最終會(huì)調(diào)用msg.target.dispatchMessage(msg)
public static void loop() {
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
final MessageQueue queue = me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
handler的dispatchMessage會(huì)把msg傳給handleCallback回調(diào)
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
看完源碼后谴餐,總結(jié)下
從handler中獲取一個(gè)消息對(duì)象,把數(shù)據(jù)封裝到消息對(duì)象中呆抑,通過handler的send…方法把消息push到MessageQueue隊(duì)列中岂嗓。
Looper對(duì)象會(huì)輪詢MessageQueue隊(duì)列,把消息對(duì)象取出鹊碍。
通過dispatchMessage分發(fā)給Handler厌殉,再回調(diào)用Handler實(shí)現(xiàn)的handleMessage方法處理消息
Handler的實(shí)現(xiàn)中適及以下對(duì)象:
1、Handler本身:負(fù)責(zé)消息的發(fā)送和處理
2侈咕、Message:消息對(duì)象
3公罕、MessageQueue:消息隊(duì)列(用于存放消息對(duì)象的數(shù)據(jù)結(jié)構(gòu))
4、Looper:消息隊(duì)列的處理者(用于輪詢消息隊(duì)列的消息對(duì)象耀销,取出后回調(diào)handler的dispatchMessage進(jìn)行消息的分發(fā)熏兄,dispatchMessage方法會(huì)回調(diào)handleMessage方法把消息傳入,由Handler的實(shí)現(xiàn)類來處理)
Message對(duì)象的內(nèi)部實(shí)現(xiàn)是鏈表树姨,最大長度是50摩桶,用于緩存消息對(duì)象,達(dá)到重復(fù)利用消息對(duì)象的目的帽揪,以減少消息對(duì)象的創(chuàng)建硝清,所以通常我們要使用obtainMessage方法來獲取消息對(duì)象
安全:
Handler的消息處理機(jī)制是線程安全的
關(guān)系:
創(chuàng)建Handler時(shí)會(huì)創(chuàng)建Looper,Looper對(duì)象的創(chuàng)建又創(chuàng)建了MessageQueue
Looper實(shí)現(xiàn)原理分析
內(nèi)部用ThreadLocal維持不同線程的Looper對(duì)象
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
ThreadLocal原理分析
ThreadLocal類用來提供線程內(nèi)部的局部變量转晰。這些變量在多線程環(huán)境下訪問(通過get或set方法訪問)時(shí)能保證各個(gè)線程里的變量相對(duì)獨(dú)立于其他線程內(nèi)的變量芦拿,ThreadLocal實(shí)例通常來說都是private static類型。
總結(jié):ThreadLocal不是為了解決多線程訪問共享變量查邢,而是為每個(gè)線程創(chuàng)建一個(gè)單獨(dú)的變量副本蔗崎,提供了保持對(duì)象的方法和避免參數(shù)傳遞的復(fù)雜性
ThreadLocal類中有一個(gè)靜態(tài)內(nèi)部類ThreadLocalMap(其類似于Map),用鍵值對(duì)的形式存儲(chǔ)每一個(gè)線程的變量副本扰藕,ThreadLocalMap中元素的key為當(dāng)前ThreadLocal對(duì)象缓苛,而value對(duì)應(yīng)線程的變量副本,每個(gè)線程可能存在多個(gè)ThreadLocal
引用鏈接
https://blog.csdn.net/blackzhangwei/article/details/51945516
https://blog.csdn.net/lhqj1992/article/details/52451136