Android開發(fā)使用Message對象分發(fā)必備知識點詳解
Message的創(chuàng)建
消息Message
一般不支持大家直接通過new
的方式進行創(chuàng)建的,因為Message
作為Android系統(tǒng)中使用頻率非常高的一個對象,如果每次都泛濫的直接創(chuàng)建一個新的,對性能是有一定影響的,而通過對象池的方式進行復(fù)用 ,則是非常好的一種方式。
Message
中就提供了這樣的一個對象池(最大緩存消息數(shù)量為50):
通過鏈表的形式將一個個待復(fù)用的緩存Message
連接起來。并且提供了obtain()
方法負責從對象池中獲取一個Message
:
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(); }
當消息調(diào)度完畢時,會通過recycleUnchecked()
方法進行回收并放入到對象池:
void recycleUnchecked() { flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; ... synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } }
重置要回收的Message
的各個成員屬性,然后添加到對象池sPool
。
消息分發(fā)執(zhí)行的三種方式
消息調(diào)度分發(fā)最終是在Looper.loopOnce()
中執(zhí)行,我們看下源碼:
private static boolean loopOnce(final Looper me, final long ident, final int thresholdOverride) { Message msg = me.mQueue.next(); // might block if (msg == null) { return false; } try { msg.target.dispatchMessage(msg); } msg.recycleUnchecked(); return true; }
核心就是msg.target.dispatchMessage()
,我們看下具體的方法邏輯:
public void dispatchMessage(@NonNull Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
源碼一目了然,接下來我們一個個的進行分析:
- 先檢測
Message
的callback
是否為null,不為null就執(zhí)行callback
的run
方法調(diào)度執(zhí)行,這個一般是如何傳入的呢:
public final boolean post(@NonNull Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); } private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }
很熟悉的post()
方法就并不再過多介紹了。
- 然后檢測
Hander
的mCallback
是否為null,不為null就執(zhí)行mCallback.handleMessage()
,這個是什么時候傳入的呢:
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; }
通過Handler
構(gòu)造方法時作為構(gòu)造參數(shù)傳入,可以選擇性使用。
- 上面都不滿足,就調(diào)用
Handler
自身的handleMessage()
方法調(diào)度執(zhí)行,這也是我們常用的消息執(zhí)行的一種方式,一般都是創(chuàng)建Handler
對象時重寫這個該方法:
fun test333() { val handler = object : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { super.handleMessage(msg) } } }
以上三種消息分發(fā)方式第一種和第三種使用的頻率比較高,第二種這種方式可以作為一種hook的手段攔截某些消息的原本調(diào)度邏輯,實現(xiàn)功能增強。
比如Activity、Service
等組件的調(diào)度是通過ApplicationThread
通過Handler
分發(fā)到主線程進行調(diào)度執(zhí)行,如果你想監(jiān)聽其生命周期,就可以通過上面的第二種方式結(jié)合反射給負責分發(fā)的Handler
注入一個mCallback
屬性值。
總結(jié)
本篇文章主要是介紹了Message
創(chuàng)建的正確方式,以及其如何在Handler
中調(diào)度分發(fā)的,每個流程是什么,希望能給你帶來幫助。
更多關(guān)于Android開發(fā)Message對象的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android打印機--小票打印格式及模板設(shè)置實例代碼
這篇文章主要介紹了Android打印機--小票打印格式及模板設(shè)置實例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-04-04Android筆記之:onConfigurationChanged詳解
本篇是對Android中onConfigurationChanged的使用進行了詳細的分析介紹。需要的朋友參考下2013-05-05Android自定義view仿QQ的Tab按鈕動畫效果(示例代碼)
這篇文章主要介紹了Android自定義view仿QQ的Tab按鈕動畫效果(示例代碼),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考價值,需要的朋友可以參考下2021-01-01Android開發(fā)教程之ContentProvider數(shù)據(jù)存儲
這篇文章主要介紹了Android開發(fā)教程之ContentProvider數(shù)據(jù)存儲的相關(guān)資料,需要的朋友可以參考下2016-12-12Android應(yīng)用的Material設(shè)計中圖片的相關(guān)處理指南
這篇文章主要介紹了Android應(yīng)用的Material設(shè)計中圖片的相關(guān)處理指南,除了介紹新的方法外文中還給出了一些設(shè)計標準樣例僅供參考,需要的朋友可以參考下2016-04-04Flutter實現(xiàn)網(wǎng)絡(luò)請求的方法示例
這篇文章主要介紹了Flutter實現(xiàn)網(wǎng)絡(luò)請求的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-03-03kotlin 官方學(xué)習(xí)教程之基礎(chǔ)語法詳解
這篇文章主要介紹了kotlin 官方學(xué)習(xí)教程之基礎(chǔ)語法詳解的相關(guān)資料,需要的朋友可以參考下2017-05-05Android viewpager無限輪播獲取網(wǎng)絡(luò)圖片功能
這篇文章主要為大家詳細介紹了Android viewpager無限輪播獲取網(wǎng)絡(luò)圖片功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-09-09