源碼學習
Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
//TODO Handler your Message
}
}
我們在定義使用 Handler時,通常如上所寫,先查看Handler的構(gòu)造函數(shù):
final MessageQueue mQueue;
final Looper mLooper;
public Handler() {
...... //省略了 Handler class 是不是 static or leaks 的檢測代碼
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = null;
}
在Handler的構(gòu)造函數(shù)中做了如下事情:
-
mLooper = Looper.myLooper();
獲取Looper對象 -
mQueue = mLooper.mQueue;
從Looper中獲取MessageQueue對象
既然 Handler 、MessageQueue 都與 Looper 有關(guān)連,先看下Looper的內(nèi)容:
//當前線程對象
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//獲取當前線程綁定的Looper對象
public static Looper myLooper() {
return sThreadLocal.get();
}
//創(chuàng)建一個Looper對象綁定到當前線程
//并在prepare的注解中,我們知道Looper的執(zhí)行過程 prepare() -> loop() -> quit() ,后面跟著這個流程解析
public static void prepare() {
//當前線程只能綁定一個Looper對象
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//當前線未綁定Looper對象,則創(chuàng)建 Looper對象并綁定到當前線程
sThreadLocal.set(new Looper());
}
//Looper 的構(gòu)造函數(shù)是默認構(gòu)造函數(shù)
private Looper() {
//創(chuàng)建了一個MessageQueue
mQueue = new MessageQueue();
mRun = true;
//綁定了當前線程
mThread = Thread.currentThread();
}
在Looper中:
- 綁定當前線程創(chuàng)建Looper對象,且當前線程只能綁定一個Looper對象
- 并創(chuàng)建了MessageQueue 對象,即Looper對象中綁定了MessageQueue對象
現(xiàn)在查看 loop() 方法,它是一個靜態(tài)方法
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
//獲取當前線程的Looper對象
Looper me = myLooper();
//不存在,則拋出異常
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//獲取綁定的消息隊列
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();
//注意:這里有一個死循環(huán),不斷從消息隊列中取消息
while (true) {
//從消息隊列中取消息 (Message下面解析)
//這個過程可能會阻塞
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
long wallStart = 0;
long threadStart = 0;
// This must be in a local variable, in case a UI event sets the logger
//打印log
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
wallStart = SystemClock.currentTimeMicro();
threadStart = SystemClock.currentThreadTimeMicro();
}
// 這里開始分發(fā)消息, msg.target ? (查看其類型就是 Handler類型,從哪里賦值的呢?后面解析)
msg.target.dispatchMessage(msg);
//打印log
if (logging != null) {
long wallTime = SystemClock.currentTimeMicro() - wallStart;
long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
if (logging instanceof Profiler) {
((Profiler) logging).profile(msg, wallStart, wallTime,
threadStart, threadTime);
}
}
// 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);
}
//消息回收: 應該是消息在分發(fā)后,被處理完了。
msg.recycle();
}
}
}
在loop() 中,
- 在Looper 中有一個 死循環(huán),會不斷的從消息隊列中取消息、并通過Message綁定的Handler分發(fā)消息。
(我們知道Android中屏幕會不斷的被渲染,這其實就是原因)
Message 對象,很簡單就是定義了消息的幾個變量和綁定的Handler等
public class Message{
public int what;
public Object obj;
Handler target;
......
}
從上面我們,我們可以看到 消息的一個分發(fā)的過程,現(xiàn)在我們來發(fā)送消息,了解消息是如何被添加到 MessageQueue(消息隊列),消息的 target(Handler 消息處理)從何而來。
//從上面 Handler定義中繼續(xù),發(fā)送一個空消息
mHandler.sendEmptyMessage(1)
我們查看上處代碼的源碼
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
//定義了一個默認Message變量
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
...//執(zhí)行到如下方法
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
//當前線程綁定的Looper,此Looper綁定的MessageQueue
MessageQueue queue = mQueue;
//判斷消息對列是否為空,不為空,將消息添加入隊列中
if (queue != null) {
//此處將 當前Handler 綁定到Msg中
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;
}
從以上代碼,可以知道:
1. 分發(fā)處理 Message 的Handler 就是 發(fā)送此消息的Handler
至于消息的處理 Handler.handlerMessage(msg) 何時被調(diào)用,如下:
//在消息的分發(fā)后被處理
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
總結(jié) Looper、MessageQueue、Handler 和 Message 的關(guān)系如下:
當我們調(diào)用handler.sendMessage(msg)方法發(fā)送一個Message時,Message會綁定此Handler,然后Message被發(fā)送到 與當前線程綁定的Looper的MessageQueue中。當前線程綁定的Looper將會不斷的從綁定的MessageQueue中取出新的Message,通過Message綁定的Handler 進行消息分發(fā),在與Message綁定的handler的 handleMessage()方法中處理此消息。
- 一個Thread對應多個Handler
- 一個Thread對應一個Looper和MessageQueue,Handler與Thread共享Looper和MessageQueue。
- Message只是消息的載體,將會被發(fā)送到與線程綁定的唯一的- MessageQueue中,并且被與線程綁定的唯一的Looper分發(fā),被與其自身綁定的Handler消費。