版權聲明:安全
本帳號發佈文章均來自公衆號,承香墨影(cxmyDev),版權歸承香墨影全部。異步
未經容許,不得轉載。oop
最開始的時候,Android 下的 Broadcast 都是全局的,發出去的廣播,只要有匹配的接收者,就能夠收到廣播。線程
而在 Support v4 : 21 以後,提供了一種新的 Broadcast 的形式,就是 LocalBroadcast,它主要用於在同一個應用中,不一樣組件之間,發送和接收 Broadcast。設計
BroadcastReceiver 在設計之初,就是想從全局的角度去設計一個方便不一樣應用程序之間進行通訊的組件。而這樣的一個開放的設計,對單個應用程序而言,BroadcastReceiver 是存在各類安全問題的。code
而 LocalBroadcast 就是由於這個而存在的,顧名思義,它就是爲了在同一個應用程序內,進行通訊的組件。它經過 LocalBroadcastManager (如下簡稱 LBM),來實現註冊、解注、發送廣播等操做。cdn
它和原有的 BroadcastReceiver 相比而言,有什麼好處:對象
LocalBroadcast 經過 LocalBroadcastManager 來管理,在 LBM 中,提供了普通廣播使用的對應的 API,經過 LBM 中提供的 API,就能夠完成對本地廣播的操做,使用方式和普通廣播無異。blog
LBM 是一個單例對象,能夠經過 LocalBroadcastManager.getInstance(Context)
方法獲取到。生命週期
LBM 的使用,其實沒什麼好說的,直接上例子。
首先,定義一個 BroadcastReceiver ,而後在一個 Activity 的生命週期內,分別註冊和解注它,而後監聽一個按鈕的點擊,用於發送 LocalBroadcast。
正常來講,使用 sendBroadcast()
是一個異步的操做,它不會堵塞住線程,同時 LBM 也提供了對應的同步操做方法,sendBroadcastSync()
。
接下來就來探究一下 LBM 的實現原理。自己普通的廣播爲了實現跨進程,使用了 Binder 機制,而 LocalBroadcast 上面介紹的會比普通廣播跟高效,那麼接下來就看看 LBM 的實現原理,是如何作到更高效的。
LBM 自己是一個單例的實現,也就是說,在當前進程的生命週期內只有一個 LBM 對象。
直接看 LBM 的構造方法。
能夠看到,在其私有的構造方法中,實際上建立了一個基於主線程的 Looper 的 Handler,在這個 Handler 中,調用 executePendingBroadcasts()
方法,從方法名上,猜想這個方法是對接收到的廣播進行處理。
接下來就來證明咱們的猜想。
先看看註冊接收者的 registerReceiver() 方法。
能夠看到,在registerReceiver()
方法中,主要是操做了兩個對象:mReceivers、mActions,它們都是 HashMap 類型的集合。
mReceivers 主要用於維護一個 BroadcastReceiver 對象和它的 IntentFilter 對象的對應關係。主要是爲了方便在 unregisterReceiver()
方法中,快速的移除它,而且它也做爲同步對象鎖限制一些行爲的同步訪問。
而 mActions 則維護了一個以 action 爲 key,ReceiverRecord 對象爲 value 的對應關係。這樣能夠方便經過 action 找到與之匹配的 ReceiverRecord。而 ReceiverRecord 是一個內部類,主要用於存儲 receiver 和 IntentFilter。
再來看看 unregisterReceiver()
方法,其實很是的簡單,它只是按照條件,移除了 mReceivers 和 mActions 兩個對象中存儲的 BroadcastReceiver。
最關鍵的 sendBroadcast()
方法,看看它最終是如何發送這個 LocalBroadcast 的。
雖然看着挺多代碼的,可是實際上它的處理方式很簡單。先從 mActions 中取出對應的 ReceiverRecord 對象,而後在根據 IntentFilter 匹配出符合條件的 Receiver,再將其保存到 mPendingBroadcasts 對象中,最後發送一個 MSG_EXEC_PENDING_BROADCASTS 的消息給 mHandler。
後續咱們就已經知道了,mHandler 接收到 MSG_EXEC_PENDING_BROADCASTS 消息以後,就會去執行 executePendingBroadcasts()
方法。
到這裏就清晰了,它會將以前暫存在 mPendingBroadcasts 中的對象所有取出來,而後循環調用其 onReceiver() 方法,將其消費掉,完成這次廣播的發送。
那再看看同步方法 sendBroadcastSync() 方法中是如何實現的,
能夠看到,它其實是調用 sendBroadcast() 以後,當即調用 executePendingBroadcasts() 方法去執行。這樣由於在其中有同步對象鎖,而且也有對 mPendingReceivers 中數量的校驗,因此最終,發送給 mHandler 的消息執行的 executePendingBroadcasts() 方法的時候,對應的 mPendingReceivers 已經被消費掉清空了,就會被過濾掉,其實是一次無心義的調用。
到此,基本上就已經徹底瞭解了 LocalBroadcastManager 的全部細節,它之因此比普通廣播跟高效,是由於其中並無利用 Binder ,而是藉助 Handler 來實現應用內的通訊,天然安全性更好,效率更高。
其實 LocalBroadcastManager 實現的效果相似一個 EventBus 的效果,更多的狀況下,仍是推薦使用相似 EventBug 這類成熟的開源庫來完成咱們應用內通訊的需求。固然,LocalBroadcastManager 的思路仍是有值得咱們借鑑的地方的。