標(biāo)簽(空格分隔): android
前言
最近學(xué)習(xí) ios昧廷,發(fā)現(xiàn) ios 的 NSlopper 跟 Android 的 Looper 非常相似,于是就突然很想再學(xué)習(xí)一片 android 的 Looper蜡豹。
三者之間的關(guān)系
先看看大致的圖片(有點(diǎn)丑麸粮,請(qǐng)將就):Handler:就是處理者,他通過方法sendEmptyMessage(int what)或sendMessage(Message msg)或sendMessageAtTime(Message msg, long uptimeMillis)等方法(想知道更多方法镜廉,自己在 as 下敲 send 就可以看到了)給 messageQueue 發(fā)送消息弄诲。
MessageQueue:就是消息隊(duì)列(其實(shí)該類是通過鏈表實(shí)現(xiàn)的),handler 給里面發(fā)送消息,Looper 在里面拿消息齐遵。
Looper 循環(huán)者 就是不停循環(huán) MessageQueue寂玲,在里面拿消息。
這是他們之間的具體作用梗摇,下面分析具體的流程
Looper
首先我們從 Looper 說起拓哟,先看看 Looper 的 prepare() 方法。
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
上面出現(xiàn)了一個(gè)sThreadLocal
伶授,這個(gè)是一個(gè)ThreadLocal類型的變量断序,可以用該類保存數(shù)據(jù),但是作用域是相對(duì)于線程來言的糜烹。那么這段代碼的意義就是一個(gè)線程最多只能有一個(gè) Looper违诗。我們?cè)倏纯?Looper 是怎么創(chuàng)建的:
private Looper() {
mQueue = new MessageQueue();
mRun = true;
mThread = Thread.currentThread();
}
可以看到 Looper 是持有一個(gè) MessageQueue 對(duì)象的,也持有一個(gè)當(dāng)前線程的引用(調(diào)用 prepare 的地方的線程)疮蹦。這段代碼的意義就是一個(gè)Looper 擁有一個(gè)MeesageQueue诸迟,那么就是一個(gè)線程,一個(gè) Looper愕乎,一個(gè) MessageQueue阵苇,再看看 Looper 的 loop()方法。
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
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();
}
}
1.在第9行可以拿到自己的 MessageQueue
2.17到46行:就進(jìn)入了死循環(huán)了感论。
3.18行取出消息退列的最前的一條消息绅项,可以看到注解的 might block ,意思就是沒有消息的時(shí)候會(huì)堵塞笛粘。
4.23行msg.target.dispatchMessage(msg); msg變量的類型是Message趁怔,msg.target的類型是Handler湿硝。其實(shí)就是分發(fā) message 回調(diào)給用戶處理薪前,等等詳細(xì)介紹1。
5.每處理完該消息后关斜,調(diào)用msg.recycle()回收該Message對(duì)象占用的系統(tǒng)資源示括。
好了,Looper 大概流程基本完成×⌒螅現(xiàn)在來看看 MessageQueue 的作用垛膝。
MessageQueue
隊(duì)列,先進(jìn)先出丁稀,里面裝著一堆 Message 類型的變量吼拥。MessageQueue最重要的兩個(gè)函數(shù)是是next()和enquenceMessage(),分別是“取出消息”和“添加消息”到隊(duì)列中线衫。具體代碼有點(diǎn)復(fù)雜凿可,不貼出來,想知道的請(qǐng)自己看源碼= =。
Handler
我們會(huì)調(diào)用 handler的 sendEmptyMessage(int what)或sendMessage(Message msg) 方法來把 Message 添加到 MessageQueue 隊(duì)列中枯跑。
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis < 0) {
delayMillis = 0;
}
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) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
從上面代碼看到惨驶,無論哪個(gè)方法最終都會(huì)調(diào)用sendMessageAtTime(Message msg, long uptimeMillis)
這個(gè)方法×仓看看第39行粗卜,enqueueMessage(queue, msg, uptimeMillis),再調(diào)用到47行;這就是往MessageQueue
中添加 Message纳击。
好了上面流程就是 handler->sendMessage->messsageQueue->looper,就差異步 looper 回掉給 Handler 的處理续扔,在上面1已經(jīng)說了,是利用 Looper 中 loop()
方法遍歷消息焕数,然后當(dāng)獲得消息后調(diào)用 msg.target.dispatchMessage(msg); msg變量的類型是Message测砂,msg.target的類型是Handler,就是調(diào)用 Handler 的 dispatchMessage() 百匆。那么看看 dispatchMessage() 代碼砌些。
/**
* Handle system messages here.
*/
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
msg.callback.run();
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
第6行,這個(gè) msg.callback 就是我們 message 的 callback加匈,當(dāng)我們調(diào)用mHandler.post(Runnable r); 時(shí)候會(huì)給當(dāng)前 looper 的 message 賦值 runnable存璃,所以最終收到消息后就會(huì)調(diào)用改 runnable 方法。
第18行雕拼,mCallback 是在 new Handler 的時(shí)候指定的纵东,具體方法是public Handler(Callback callback, boolean async)。如果傳入為空啥寇,則我們就跑自身的 handleMessage(msg)方法偎球,就會(huì)調(diào)用我們自定義的實(shí)現(xiàn),就是我們常寫的方式辑甜。代碼:
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg)
{
switch (msg.what)
{
case value:
break;
default:
break;
}
};
};
好了衰絮,大概流程就這樣子,可以再看看這副簡陋的圖再聯(lián)想一下流程:
磷醋。