前言
首先介紹一下Handler和Looper变秦,MessageQueue分別是做什么的,有什么用!
- Handler:線程間發(fā)送與處理消息
- Looper:管理MessageQueue消息隊(duì)列,循環(huán)讀取MessageQueue中的消息
- MessageQueue:消息隊(duì)列
- Message:消息的載體
首先我們?nèi)绻谥骶€程使用Handler的話,肯定是下面的步驟:
handler = new Handler(handlerThread.getLooper()){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.d("test","Handler消息!");
}
};
為什么沒(méi)有調(diào)用Looper的方法呢货葬?
因?yàn)橹骶€程已經(jīng)默認(rèn)給我們調(diào)用了Looper的這個(gè)兩方法
Looper.prepare();
Looper.loop();
現(xiàn)在我們開始一步一步的分析
- 先從Looper的prepare和loop兩個(gè)方法開始:
prepare方法:
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
方法內(nèi)部的功能:
判斷當(dāng)前線程的Looper是否為空,如果為空就創(chuàng)建一個(gè)新的Looper對(duì)象,不為空的話就會(huì)拋出異常
這就是為什么在一個(gè)線程Looper不能調(diào)用兩次preare()方法的原因
代碼中把Looper對(duì)象存到了sThreadLocal中,這個(gè)sThreadLocal又是什么呢?
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
簡(jiǎn)單分析下ThreadLocal:
ThreadLocal內(nèi)部有個(gè)ThreadLocalMap類用來(lái)存儲(chǔ)值的,這個(gè)ThreadLocalMap使用鍵值對(duì)進(jìn)行存儲(chǔ)的婉商,在Thread類中有個(gè)ThreadLocalMap實(shí)例對(duì)象,也就是說(shuō)在每個(gè)線程都有一個(gè)ThreadLocalMap對(duì)象
ThreadLocal存取值方法
ThreadLocal.get方法:
- ThreadLocal會(huì)獲取當(dāng)前Thread的ThreadLocalMap對(duì)象然后取出值
TrheadLocal.set方法 - ThreadLocal會(huì)獲取當(dāng)前Thread的ThreadLocalMap對(duì)象然后存入值
假如我們調(diào)用Looper的myLooper()方法獲取當(dāng)前Thread的Looper,ThreadLocal就會(huì)獲取當(dāng)前Thread來(lái)取出當(dāng)前Thread的ThreadLocalMap對(duì)象,然后取出里面的Looper對(duì)象
個(gè)人覺得ThreadLocal就是可以為各個(gè)線程存儲(chǔ)其對(duì)應(yīng)的數(shù)據(jù)
貼出ThreadLocal部分代碼:
public T get() {
// 獲取當(dāng)前線程
Thread t = Thread.currentThread();
// 取出當(dāng)前線程的ThreadLocalMap對(duì)象
ThreadLocalMap map = getMap(t);
// 判斷如果map不為空就取出對(duì)應(yīng)的值
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
public void set(T value) {
// 獲取當(dāng)前線程
Thread t = Thread.currentThread();
// 取出當(dāng)前線程的ThreadLocalMap對(duì)象
ThreadLocalMap map = getMap(t);
// 判斷如果map為空則進(jìn)行創(chuàng)建
// 不為空就進(jìn)行存值
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
// 獲取線程中的threadLocals對(duì)象
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
Ok,現(xiàn)在看loop方法
我在代碼比較重要的地方注釋進(jìn)行解釋
public static void loop() {
// 獲取了當(dāng)前Thread的Looper對(duì)象
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
// 獲取當(dāng)前Looper的MessageQueue
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();
// 開始一個(gè)無(wú)限循環(huán)
// for(;;){}這種寫法就是無(wú)限循環(huán)的意思
for (;;) {
// 獲取MessageQueue中的Message對(duì)象
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
final Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
final long traceTag = me.mTraceTag;
if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
// 我們看這里
// 這里才是關(guān)鍵的地方
// 調(diào)用Message.target對(duì)象的dispatchMessage方法,target其實(shí)就是Handler的引用;
// 而Handler的dispatchMessage方法內(nèi)部又調(diào)用了handleMessage方法去處理
// 而我們每次創(chuàng)建Handler都會(huì)實(shí)現(xiàn)handlerMessage方法,是不是有點(diǎn)明白什么了.
// OK這個(gè)我們待會(huì)詳細(xì)再將
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
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();
}
}
現(xiàn)在可以看出來(lái),loop方法內(nèi)部就是開啟了一個(gè)死循環(huán),不斷的從MessageQueue中取出Message進(jìn)行處理,
通過(guò)Message.target.dispatchMessage發(fā)送Handler所在的線程取處理
Looper的preare和loop方法分析好了,現(xiàn)在我們開始從sendMessage方法一直往下分析,看下Handler從發(fā)送到處理到底經(jīng)過(guò)了哪些流程
關(guān)于Handler發(fā)送Message有兩種發(fā)送方式
簡(jiǎn)單說(shuō)下區(qū)別:
// 1 每次都會(huì)新建Message對(duì)象
Message message = new Message();
message.what = 0;
handler.sendMessage(message);
// 2 會(huì)從Message消息池中取出已存在的Message對(duì)象進(jìn)行復(fù)用
handler.obtainMessage(0).sendToTarget();
// 因?yàn)閛btainMessage會(huì)取出已存在的Message對(duì)象進(jìn)行復(fù)用,所以個(gè)人建議使用obtainMessage
好的,方便我們的理解,我們就用sendMessage開始分析,
下面是sendMessage調(diào)用過(guò)程
public final boolean sendMessage(Message msg)
{
// sendMessage方法延時(shí)時(shí)間為0,就是不延時(shí)處理
return sendMessageDelayed(msg, 0);
}
// delayMillis延時(shí)時(shí)間
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
// SystemClock.uptimeMillis() // 從開機(jī)到現(xiàn)在的毫秒數(shù)(手機(jī)睡眠的時(shí)間不包括在內(nèi))
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(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);
}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
// 設(shè)置當(dāng)前消息的目標(biāo)handler
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
我們調(diào)用sendMessage方法發(fā)送消息,sendMessage方法最終會(huì)走到enqueueMessage方法中,在enqueueMessage方法中,將message的target對(duì)象設(shè)置為當(dāng)前handler對(duì)象
剛才我們?cè)趌oop方法中是不是看到使用了message.target對(duì)象,原來(lái)target是在這里賦值的
然后看方法內(nèi)部最后調(diào)用了queue.equeueMessage方法,也就是說(shuō)調(diào)用了MessageQueue對(duì)象的enqueueMessage方法
我們跟著這個(gè)方法進(jìn)入看看
boolean enqueueMessage(Message msg, long when) {
// 如果msg.target為空拋出異常
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
// 如果msg正在處理中拋出異常
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
// 停止
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;
}
// 標(biāo)識(shí)消息開始處理
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
// 如果p == null || when == 0 || when < p.when,則將此次消息插入消息隊(duì)列頭部
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
// 將msg的下一個(gè)位置設(shè)置成當(dāng)前頭部的消息
msg.next = p;
// 再將msg賦值為mMessages
// 就完成了當(dāng)前消息插入消息隊(duì)列頭部的操作
mMessages = msg;
needWake = mBlocked;
} else { // 將此次消息插入隊(duì)列末端,或者是插入在延時(shí)消息比較長(zhǎng)時(shí)間的前面
// 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;
// 開啟無(wú)線循環(huán),其作用就是找到隊(duì)列的尾部,或者找到比此消息執(zhí)行時(shí)間還要上的消息的上一個(gè)位置
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;
}
關(guān)于enqueueMessage內(nèi)部主要進(jìn)行消息的插入隊(duì)列中
如果p == null || when == 0 || when < p.when則將該條消息插入隊(duì)列的頭部
(個(gè)人理解,p ==null 可能就是第一次插入消息時(shí),when < p.when的時(shí)候就是后面插入的消息要比頭部的消息先執(zhí)行,所以插入到頭部,先執(zhí)行意思就是延時(shí)時(shí)間要比頭部的短)
否則就把消息插入隊(duì)列的尾部,或者插入延時(shí)消息比自己時(shí)間要長(zhǎng)的前一個(gè)位置
關(guān)于插入延時(shí)消息比自己時(shí)間要長(zhǎng)的前一個(gè)位置的解釋:
比如現(xiàn)在連續(xù)發(fā)送兩個(gè)消息,第一個(gè)消息延時(shí)1分鐘處于消息池中最后一個(gè)位置,第二個(gè)消息延時(shí)3秒的海诲,此時(shí)第一個(gè)消息會(huì)被插入到延時(shí)1分鐘消息的前面
Ok此時(shí)消息已經(jīng)被插入消息隊(duì)列,那么還記得剛才的loop方法嗎,因?yàn)槭菬o(wú)限循環(huán)方法,所以被插入到隊(duì)列的消息會(huì)被Looper對(duì)象取出并處理
看代碼:
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
在loop方法中如果取到message就會(huì)調(diào)用它的target對(duì)象.dispatchMessage方法,剛才已經(jīng)說(shuō)了target就是handler對(duì)象,現(xiàn)在我們?nèi)andler中的dispatchMessage方法中看看
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
public void handleMessage(Message msg) {
}
我們先分析msg.callback和mCallback.handleMessage方法,最后再說(shuō)handleMessage(msg)方法
關(guān)于msg.callback和mCallback.handleMessage方法
msg.callback是通過(guò)Message對(duì)象設(shè)置的一個(gè)Runnable實(shí)現(xiàn)對(duì)象,當(dāng)前消息發(fā)送之后會(huì)出發(fā)該實(shí)現(xiàn)方法
關(guān)于調(diào)用的handleCallback只是竹筏msg.callback的run方法
private static void handleCallback(Message message) {
message.callback.run();
}
關(guān)于會(huì)走msg.callback的寫法
Message m = Message.obtain(handler, new Runnable() {
@Override
public void run() {
}
});
m.sendToTarget();
mCallback.handleMessage可以看下面的代碼就會(huì)明白
handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message message) {
return false;
}
});
mCallback是通過(guò)構(gòu)造傳入的一個(gè)接口,而這個(gè)接口中有個(gè)方法也是handleMessage(msg)方法
看代碼:
Handler內(nèi)部的CallBack接口
···
/**
* Callback interface you can use when instantiating a Handler to avoid
* having to implement your own subclass of Handler.
*
* @param msg A {@link android.os.Message Message} object
* @return True if no further handling is desired
*/
public interface Callback {
public boolean handleMessage(Message msg);
}
···
最后說(shuō)我們重寫的handleMessage方法
如果我們沒(méi)有使用以上兩種方式,而是使用重寫handleMessage方法,
也就是這種:
handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
那么在dispatchMessage中就會(huì)走到else的最后面調(diào)用了handlerMessage(msg)方法,而我們又實(shí)現(xiàn)了handleMessage方法,
所以消息會(huì)在handleMessage方法中處理掉;