Android 消息機(jī)制問題總結(jié)
Android的消息機(jī)制幾乎是面試必問的話題,當(dāng)然也并不是因?yàn)槊嬖?,而去學(xué)習(xí),更重要的是它在Android的開發(fā)中是必不可少的,占著舉足輕重的地位,所以弄懂它是很有必要的。下面就來說說最基本的東西。
Looper
作用:
關(guān)聯(lián)起Thread
循環(huán)取出消息
1、Looper是否可以直接實(shí)例化?
Looper構(gòu)造方法是私有的,其中做了兩件事
創(chuàng)建一個(gè)MessageQueue
得到與之對應(yīng)的Thread
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
2、一個(gè)線程能對應(yīng)多個(gè)Lopper?
不能,一個(gè)線程對應(yīng)一個(gè)Looper對象,通過ThreadLocal保證一個(gè)線程只有一個(gè)Looper與之對應(yīng),如果多次調(diào)用Looper.prepare();則會拋出運(yùn)行時(shí)異常。
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { // 查看是否有l(wèi)ooper與當(dāng)前線程對應(yīng) throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
3、Looper是無限循環(huán),會阻塞嗎?
是,當(dāng)開啟一個(gè)loop后是一個(gè)死循環(huán),從MessageQueue中取出消息,處理消息,但是也有可能退出,在沒有消息后退出循環(huán)。
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; // 略 for (;;) { Message msg = queue.next(); // might block if (msg == null) { // 當(dāng)沒有消息的時(shí)候,退出 // No message indicates that the message queue is quitting. return; } // 略 msg.target.dispatchMessage(msg); }
4、可以再次調(diào)用Looper.prepareMainLooper嗎?
不可以,Looper.prepareMainLooper最終也是調(diào)用prepare(),同2.
public static void prepareMainLooper() { prepare(false); // 創(chuàng)建一個(gè)Looper synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } }
5、MainLooper什么時(shí)候創(chuàng)建的?
MainLooper是啟動Activity創(chuàng)建ActivityThread(并不是一個(gè)Thread)時(shí)候創(chuàng)建,所以不能多次創(chuàng)建。
public static void main(String[] args) { // 略 Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); // 略 ActivityThread thread = new ActivityThread(); thread.attach(false); // 略 if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } // 略 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); } }
Handler
作用:
發(fā)送消息到MessageQueue
處理消息
1、Handler如何與Looper、MessageQueue關(guān)聯(lián)起來?
我們知道一個(gè)Looper對應(yīng)一個(gè)Thread,一個(gè)Looper包含一個(gè)MessageQueue。當(dāng)我們創(chuàng)建Handler時(shí)就會從當(dāng)前線程中取出與之對應(yīng)的Looper,讓后在從Looper中取出MessageQueue。
// 1、自動獲取 public Handler(Callback callback, boolean async) { // 略 mLooper = Looper.myLooper(); // 取出當(dāng)前線程中的Looper if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; // 取出MessageQueue mCallback = callback; mAsynchronous = async; } // 2、傳遞一個(gè)Looper進(jìn)來 public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; }
Message
單項(xiàng)鏈表結(jié)構(gòu)。
作用:
數(shù)據(jù)的載體
1、消息如何復(fù)用的?
從全局消息池(鏈表結(jié)構(gòu))中
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(); }
2、Message為什么能傳遞?
Android中想要傳遞對象要么實(shí)現(xiàn)Serializable要么Parcelable,在這里是實(shí)現(xiàn)了Parcelable接口。
public final class Message implements Parcelable {
// 略
}
3、如何與Handler關(guān)聯(lián)?
我們知道在消息傳機(jī)制中Handler充當(dāng)著“快遞員”的角色,那么他又是如何與“貨物”--Message發(fā)生關(guān)系呢?實(shí)際上Message有一個(gè)成員變量target他的類型正是Handler,
/*package*/ Runnable callback; public int arg1; public int arg2; public Object obj; /*package*/ Handler target; // 關(guān)鍵點(diǎn)
當(dāng)我們通過Handler去send一個(gè)Message時(shí)候最終都會為target賦值為this,即當(dāng)前的Handler。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; // 賦值語句 if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
另為如果是通過Message.Obtain(),獲取的復(fù)用Message也會為其賦值。
多說一句,Handler.obtainMessage()調(diào)用的就是Message.Obtain()。
public final Message obtainMessage(){ return Message.obtain(this); }
總結(jié):
通過一系列的包涵關(guān)系,最終Looper、Handler、Message、MessageQueue即發(fā)生關(guān)聯(lián),從而形成一個(gè)閉合,開啟消息循環(huán)。
困惑
最近一直在看這方面的知識,但是能力有限,還是有不少困惑,如果有錯(cuò)誤,或你理解下面的問題請聯(lián)系我fvaryu@qq.com,愿與君交流學(xué)習(xí),謝謝
1、Message中的sPool,哪里初始化的?為什么Message.obtain()中不會拋異常?
2、ActivityThread并不是線程,為什么可以創(chuàng)建一個(gè)Looper,Main Thread什么時(shí)候創(chuàng)建?
3、為什么序列化了的對象就可以傳遞?與Binder有關(guān)?
4、MessageQueue對應(yīng)的是NativeMessageQueue,具體實(shí)現(xiàn)需要學(xué)習(xí)?
5、Loop.loop(),會退出嗎?退出時(shí)機(jī)是什么?如果會退出,那么主線程同樣會退出嗎?
以上就是對Android 消息機(jī)制的資料整理,后續(xù)繼續(xù)補(bǔ)充相關(guān)資料,謝謝大家對本站的支持
- android異步消息機(jī)制 源碼層面徹底解析(1)
- 代碼分析Android消息機(jī)制
- Android異步消息機(jī)制詳解
- android線程消息機(jī)制之Handler詳解
- android利用消息機(jī)制獲取網(wǎng)絡(luò)圖片
- Android 消息機(jī)制詳解及實(shí)例代碼
- Android的消息機(jī)制
- Android消息機(jī)制Handler的工作過程詳解
- 深入剖析Android消息機(jī)制原理
- Android 消息機(jī)制以及handler的內(nèi)存泄露
- Android6.0 消息機(jī)制原理解析
- 深入淺析Android消息機(jī)制
- Android編程中的消息機(jī)制實(shí)例詳解
- Android編程之消息機(jī)制實(shí)例分析
- android異步消息機(jī)制 從源碼層面解析(2)
相關(guān)文章
Framework源碼面試之a(chǎn)ctivity啟動流程
這篇文章主要為大家介紹了Framework源碼面試之a(chǎn)ctivity啟動流程實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09ReactiveCocoa代碼實(shí)踐之-RAC網(wǎng)絡(luò)請求重構(gòu)
這篇文章主要介紹了ReactiveCocoa代碼實(shí)踐之-RAC網(wǎng)絡(luò)請求重構(gòu) 的相關(guān)資料,需要的朋友可以參考下2016-04-04Android網(wǎng)絡(luò)通信的實(shí)現(xiàn)方式
這篇文章主要為大家詳細(xì)介紹了Android網(wǎng)絡(luò)通信的實(shí)現(xiàn)方式,四種實(shí)現(xiàn)網(wǎng)絡(luò)通信的方式供大家學(xué)習(xí),感興趣的小伙伴們可以參考一下2016-06-06Android RecyclerView的Item自定義動畫及DefaultItemAnimator源碼分析
這篇文章主要介紹了Android RecyclerView的Item自定義動畫及DefaultItemAnimator源碼,感興趣的小伙伴們可以參考一下2016-07-07Flutter實(shí)現(xiàn)滾動選擇數(shù)字
這篇文章主要為大家詳細(xì)介紹了Flutter實(shí)現(xiàn)滾動選擇數(shù)字,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03使用AccessibilityService實(shí)現(xiàn)微信自動切換賬號功能
這篇文章主要為大家詳細(xì)介紹了使用AccessibilityService實(shí)現(xiàn)微信自動切換賬號功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12Android Listview點(diǎn)贊問題關(guān)于圖片重復(fù)問題
最近在開發(fā)android方面的項(xiàng)目時(shí),遇到很多問題,下面小編以listview 與 baseadapter結(jié)合使用為例,給大家分享下關(guān)于點(diǎn)贊的的時(shí)候 圖片重復(fù)問題的解決方法,一起看看吧2016-11-11