前面兩篇文章分別講了Handler的消息發(fā)送和Message入列、Message的創(chuàng)建和Message在隊(duì)列中的存在形式,那么MessageQueue是怎么來(lái)的?因?yàn)槲覀冊(cè)趧?chuàng)建Handler和發(fā)送Message時(shí)并沒(méi)有創(chuàng)建MessageQueue,那這個(gè)消息隊(duì)列從何而來(lái)呢?上源碼:
//省略了部分代碼public Handler(Callback callback, boolean async) { mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.以上為Handler的構(gòu)造方法,Handler的構(gòu)造方法共有7個(gè),大多數(shù)構(gòu)造方法都指向了這個(gè)兩個(gè)參數(shù)的構(gòu)造方法。從這個(gè)構(gòu)造方法中,我們看到了mQueue = mLooper.mQueue說(shuō)明消息隊(duì)列MessageQueue為L(zhǎng)ooper的一個(gè)成員變量,mLooper是有Looper類(lèi)中的靜態(tài)方法Looper.myLooper()獲取://Looper類(lèi)static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();public static @Nullable Looper myLooper() { return sThreadLocal.get(); }在Looper.myLooper()方法中調(diào)用sThreadLocal.get(),源碼繼續(xù):
看到這里其實(shí)我是懵逼的(相信大家也都有點(diǎn)懵逼吧)。在這個(gè)方法中去獲取了當(dāng)前的線程,看到這里我們至少知道Looper對(duì)象是和線程相關(guān)的。再來(lái)看看這段代碼:
//Looper類(lèi)static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();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.prepare()方法中我們看到了sThreadLocal.set(new Looper(quitAllowed));,結(jié)合上面的sThreadLocal.get()至少可以看出一個(gè)是放入,另一個(gè)方法是取出。那為什么我們?cè)跊](méi)有調(diào)用Looper.prepare()方法時(shí)還能拿到Looper對(duì)象呢?準(zhǔn)確的說(shuō)在主線程為什么我們能拿到Looper對(duì)象呢。為此查了下資料。以下資料來(lái)自Android中為什么主線程不會(huì)因?yàn)長(zhǎng)ooper.loop()里的死循環(huán)阻塞?
我們知道APP的入口是在ActivityThread,一個(gè)java類(lèi),有著main方法,而且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()); AndroidKeyStoreProvider.install(); // Make sure TrustedCertificateStore looks in the right place for CA certificates final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); Process.setArgV0("<pre-initialized>"); 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"); }從上述代碼中可以看出,APP在啟動(dòng)時(shí)就會(huì)在主線程中調(diào)用Looper.prepareMainLooper(),所以在主線程中一開(kāi)始就存在著Looper對(duì)象,從Looper.prepare()方法中可以看出,一個(gè)線程中只能存在一個(gè)Looper對(duì)象,所以我們?cè)谥骶€程發(fā)送消息時(shí)并不需要自己創(chuàng)建新的Looper對(duì)象,但是在工作線程中使用Handler就必須手動(dòng)調(diào)用Looper.prepare()方法。這下我們知道了Looper的來(lái)源,MessageQueue的由來(lái)也非常明確了。
在Looper.prepare()方法中調(diào)用了Looper的構(gòu)造方法,而就在Looper的構(gòu)造方法中創(chuàng)建了MessageQueue。
系列目錄:
一定搞懂Handler消息處理機(jī)制系列之「01.Handler消息發(fā)送」
一定搞懂Handler消息處理機(jī)制系列之「02.Message入列」
一定搞懂Handler消息處理機(jī)制系列之「03.MessageQueue與Looper的由來(lái)」
一定搞懂Handler消息處理機(jī)制系列之「04.Message是如何觸發(fā)的」
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注