摘要:在這里表示的是不允許退出。這之后會調用到進入實質性的工作函數中。看到了吧,由于函數運行在主線程中,因此以上這些都是在主線程中運行的代碼。注意,這個是排他性的,如果前面的可以執行就不會走后面的。現在比較清楚了吧,整個消息循環是如何運轉的。
本來是不想寫這篇文章的,但是很早以前看過的東西容易遺忘,希望還是給自己一個記錄吧,另外此篇希望能夠寫的深入一些。
looper是什么就不介紹了吧,一個線程的消息泵,handler是消息的操作者,messagequeue是消息隊列。
我們從源頭開始看起,activity里的主ui線程就是ActivityThread mMainThread。這個ActivityThread的main函數會在程序創建的時候被調用,那么看下內部:
public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); SamplingProfilerIntegration.start(); // CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. CloseGuard.setEnabled(false); Environment.initForCurrentUser(); // Set the reporter for event logging in libcore EventLogger.setReporter(new EventLoggingReporter()); // Make sure TrustedCertificateStore looks in the right place for CA certificates final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); Process.setArgV0(""); Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
首先走了Looper.prepareMainLooper();這個是與普通線程創建looper不同的地方,普通的都是prepare方法調用。那么看看里面:
public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }
還是prepare,但是傳遞的參數是false。在這里表示的是不允許退出。再來就是prepare:
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)); }
存儲線程本地對象中一個新的looper。同時可以看到,如果已經存在了這個線程本地對象,那么直接報錯,也就是說一個線程只允許一個looper存在。
回到ActivityThread的main,初始化好之后就是sMainThreadHandler = thread.getHandler();這個getHandler里直接返回的是mH,其實就是一個Handler的子類H。這個H是個很長的類,就是定義好的對activity默認相應的各項。
這之后會調用到Looper.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 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)); } 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(); } }
首先看到在Looper的構造函數里就創建了MessageQueue:
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
那么這個loop函數中就直接取過來用,后面是個死循環,不斷的通過queue.next()獲取新的消息,并最終調用msg.target.dispatchMessage(msg);來處理。至此looper分析完了。下面看看Message的msg.target.dispatchMessage(msg);是怎么調用的:
看到message的時候,他的target就是Handler。這下子串上了吧,在looper的loop函數循環中枚舉新message,并交給message里的Handler的dispatchMessage函數處理。那么好吧,我們回顧下,在發送message的時候,一般先obtain獲取一個消息,我們看看:
public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; m.flags = 0; // clear in-use flag sPoolSize--; return m; } } return new Message(); }
看起來像鏈表是吧,每次取得時候將sPool給m,sPool移動到下一個,然后將sPoolSize減一,最后返回m。再看下回收部分:
void recycleUnchecked() { // Mark the message as in use while it remains in the recycled object pool. // Clear out all other details. flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; sendingUid = -1; when = 0; target = null; callback = null; data = null; synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } }
這里將自己賦值給sPool,然后sPoolSize++,看到這里應當明白,其實就是個鏈表的應用,保證sPool指向的是空閑的message的第一個。
然后呢,應用的時候會調用Handler的sendMessage函數,并且將參數設置為剛才獲取到的空閑message,對吧。那么我們看看這個sendMessage,最終會調用到sendMessageAtTime中:
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); }
這里出現了MessageQueue,然后會走到enqueueMessage:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
第一句就是msg.target = this;,清楚了吧,這里將message的target賦值為handler自身。那么回到loop這個函數中,會走到msg.target.dispatchMessage(msg);這句話,實際上就是在走handler的msg.target.dispatchMessage。再進入到handler中看看這個dispatchMessage:
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
能看到什么?先試圖調用message的callback,如果沒有則試圖調用自身的mCallback的handleMessage,如果還沒有,好吧,直接走handleMessage。依次看一下,首先是handleCallback:
private static void handleCallback(Message message) { message.callback.run(); }
這個callback是個什么呢?可以通過Message的obtain看到:
public static Message obtain(Handler h, Runnable callback) { Message m = obtain(); m.target = h; m.callback = callback; return m; }
一個runnable,那么這個runnable是何時被賦值的呢?看Handler中:
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); }
看到了吧,這里在執行post的時候給的runnable就是這個callback。那么再想想,我們在寫代碼的時候,很多時候都會走一個handler的post或者postDelayed,執行一段代碼在主線程中,這個傳遞進來的runnable就是message的callback了。順便說下,View里的post也是調用的這個東西。
下面是Handler自身的mCallback了,在構造Handler的時候可以指定一個callback傳遞進來,這個Callback是這樣定義的:
public interface Callback { public boolean handleMessage(Message msg); }
指定的話就會走這個標準的回調,否則最后會走Handler的handleMessage,這個才是我們最常用的繼承下來的函數。看到了吧,由于loop函數運行在主線程中,因此以上這些都是在主線程中運行的代碼。注意,這3個是排他性的,如果前面的可以執行就不會走后面的。
現在比較清楚了吧,整個消息循環是如何運轉的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/66767.html
摘要:輔助功能類,提供接口向消息池中發送各類消息事件,并且提供響應消息的機制。進入消息泵循環體,以阻塞的方式獲取待處理消息。執行消息的派發。并且將返回值保存在了。我們深入下去看看層的部分,在這里明顯生成了一個新的,并且將地址作為返回值返回了。 概述 android里的消息機制是非常重要的部分,這次我希望能夠系統的剖析這個部分,作為一個總結。首先這里涉及到幾個部分,從層次上看,分為java層和...
摘要:在子線程中發送消息,主線程接受到消息并且處理邏輯。也稱之為消息隊列,特點是先進先出,底層實現是單鏈表數據結構得出結論方法初始話了一個對象并關聯在一個對象,并且一個線程中只有一個對象,只有一個對象。 目錄介紹 1.Handler的常見的使用方式 2.如何在子線程中定義Handler 3.主線程如何自動調用Looper.prepare() 4.Looper.prepare()方法源碼分析...
摘要:在子線程中發送消息,主線程接受到消息并且處理邏輯。子線程往消息隊列發送消息,并且往管道文件寫數據,主線程即被喚醒,從管道文件讀取數據,主線程被喚醒只是為了讀取消息,當消息讀取完畢,再次睡眠。 目錄介紹 1.Handler的常見的使用方式 2.如何在子線程中定義Handler 3.主線程如何自動調用Looper.prepare() 4.Looper.prepare()方法源碼分析 5....
摘要:通過向消息池發送各種消息事件通過處理相應的消息事件。消息泵通過不斷地從中抽取,按分發機制將消息分發給目標處理者。也稱之為消息隊列,特點是先進先出,底層實現是單鏈表數據結構。目錄介紹 6.0.0.1 談談消息機制Hander作用?有哪些要素?流程是怎樣的?簡單說一下你的看法! 6.0.0.2 為什么一個線程只有一個Looper、只有一個MessageQueue,可以有多個Handler? 6...
閱讀 3069·2021-09-28 09:43
閱讀 902·2021-09-08 09:35
閱讀 1440·2019-08-30 15:56
閱讀 1183·2019-08-30 13:00
閱讀 2732·2019-08-29 18:35
閱讀 1829·2019-08-29 14:07
閱讀 3432·2019-08-29 13:13
閱讀 1333·2019-08-29 12:40