国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

一定搞懂Handler消息處理機(jī)制系列之「03.MessageQueue與Looper的由來(lái)」

2019-11-06 09:54:20
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

MessageQueue與Looper的由來(lái)

前面兩篇文章分別講了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ù):

//ThreadLocal類(lèi)public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue(); }

看到這里其實(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類(lèi)private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }

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ā)的」


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 金堂县| 镶黄旗| 连城县| 吐鲁番市| 伊川县| 繁峙县| 伊金霍洛旗| 行唐县| 高台县| 定远县| 鄱阳县| 金堂县| 龙海市| 沭阳县| 新安县| 吴桥县| 新乐市| 灵璧县| 卓资县| 柳州市| 巴彦淖尔市| 小金县| 阜新市| 金沙县| 平定县| 杭锦旗| 尚志市| 师宗县| 左云县| 孙吴县| 马山县| 张家界市| 大埔区| 专栏| 安康市| 信阳市| 育儿| 云林县| 太仓市| 潼关县| 樟树市|