Android 本地廣播 LocalBroadcastManager
LocalBroadcastManager 相信有不少人會有點認生,他是android.support.v4中的一個類,本地廣播,只在App內部傳播,大家熟知的廣播,BrocastReceiver是全域性廣播,可以跨程序通訊,而LocalBroadcastManager,只是作為一個本地訊息和資料傳輸的手段,當然,還是有不少人再用EventBus這類的訊息事件庫,不過我不喜歡用第三方的庫,雖然EventBus也比較小,之前一直在使用BrocastReceiver,也比較隨意,後來接觸的專案多了,很多事情就需要考慮到了。
使用LocalBroadcastManager的好處:
- 只能傳輸在App內部,不會被其他App接收,確保資料安全
- 接收不到其他App廣播,免干擾
- 比BrocastReceiver更加高效
不過要注意的是,LocalBroadcastManager不能靜態註冊,只能動態註冊,這一特性也反應了第二點,不需要接收其他App的廣播,那麼我們來看下如何使用吧:
private LocalBroadcastManager lm; private TestReceiver testReceiver; private void initReceiver() { //獲取例項 lm = LocalBroadcastManager.getInstance(this); IntentFilter intentFilter = new IntentFilter("com.android.Test"); testReceiver = new TestReceiver(); //繫結 lm.registerReceiver(testReceiver,intentFilter); } private class TestReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { String action= intent.getAction(); Toast.makeText(MainActivity.this, "action:" + action, Toast.LENGTH_SHORT).show(); } } @Override protected void onDestroy() { super.onDestroy(); //解綁 lm.unregisterReceiver(testReceiver); }
使用的方式和BrocastReceiver也差不多,但是要注意的就是,我們用過LocalBroadcastManager.getInstance獲取例項後,註冊,解綁和傳送都需要這個例項才可以
原始碼
我們來看下LocalBroadcastManager的原始碼是如何工作的,其實他的原始碼也沒有多少,他獲取是通過單例來實現的
@NonNull public static LocalBroadcastManager getInstance(@NonNull Context context) { Object var1 = mLock; synchronized(mLock) { if (mInstance == null) { mInstance = new LocalBroadcastManager(context.getApplicationContext()); } return mInstance; } } private LocalBroadcastManager(Context context) { this.mAppContext = context; this.mHandler = new Handler(context.getMainLooper()) { public void handleMessage(Message msg) { switch(msg.what) { case 1: LocalBroadcastManager.this.executePendingBroadcasts(); break; default: super.handleMessage(msg); } } }; }
單例後,在建構函式裡初始化了一個Handler,這個Handler我們等下將,接著我們先來看下他的註冊:
public void registerReceiver(@NonNull BroadcastReceiver receiver, @NonNull IntentFilter filter) { HashMap var3 = this.mReceivers; synchronized(this.mReceivers) { //構建廣播訊息體 LocalBroadcastManager.ReceiverRecord entry = new LocalBroadcastManager.ReceiverRecord(filter, receiver); ArrayList<LocalBroadcastManager.ReceiverRecord> filters = (ArrayList)this.mReceivers.get(receiver); if (filters == null) { filters = new ArrayList(1); //新增接收者 this.mReceivers.put(receiver, filters); } filters.add(entry); for(int i = 0; i < filter.countActions(); ++i) { String action = filter.getAction(i); ArrayList<LocalBroadcastManager.ReceiverRecord> entries = (ArrayList)this.mActions.get(action); if (entries == null) { entries = new ArrayList(1); //關聯廣播 this.mActions.put(action, entries); } entries.add(entry); } } }
註冊的時候,他先構建了一個廣播資訊體ReceiverRecord,並且將我們註冊傳入的資訊新增到Receiver,然後遍歷Action,並且關聯Action和事件,然後呼叫sendBroadcast去傳送廣播,他對資料做了處理之後,開始分類,也就有了我們的Bundler,Data之類的資料了,其實最後呼叫的程式碼:
this.mPendingBroadcasts.add(new LocalBroadcastManager.BroadcastRecord(intent, receivers)); if (!this.mHandler.hasMessages(1)) { this.mHandler.sendEmptyMessage(1); }
就是這一段,這一段也很簡單,將廣播加入mPendingBroadcasts後傳送一個What為1的Handler,而這個Handler就是之前獲取單例後他在構造方法裡建立的,所以你看這個what=1的判斷裡,他最終執行的函式為executePendingBroadcasts,程式碼不多,可以貼出來:
void executePendingBroadcasts() { while(true) { HashMap var2 = this.mReceivers; LocalBroadcastManager.BroadcastRecord[] brs; synchronized(this.mReceivers) { int N = this.mPendingBroadcasts.size(); if (N <= 0) { return; } brs = new LocalBroadcastManager.BroadcastRecord[N]; this.mPendingBroadcasts.toArray(brs); this.mPendingBroadcasts.clear(); } for(int i = 0; i < brs.length; ++i) { LocalBroadcastManager.BroadcastRecord br = brs[i]; int nbr = br.receivers.size(); for(int j = 0; j < nbr; ++j) { LocalBroadcastManager.ReceiverRecord rec = (LocalBroadcastManager.ReceiverRecord)br.receivers.get(j); if (!rec.dead) { rec.receiver.onReceive(this.mAppContext, br.intent); } } } } }
我們可以通過這個雙層for迴圈看到他最終是取得了監聽的廣播訊息體brs裡的資料,得到一個BroadcastRecord,然後呼叫br.receivers.get獲取到接收物件rec,再通過rec.receiver.onReceive通知監聽著,實現了訊息的傳送和接收
整個設計理念就是觀察者模式了,物件一對多的關係依賴,當一個物件發生改變的時候,他的所有依賴者都將受到通知並且自動更新。
開車完畢,Over!!!
福利1 免費直播課程
《騰訊課堂Android高階開發工程師系列直播》
適聽人群:Android初、中、高階開發工程師
每晚8點準時直播,持續進行
福利2 Android開發資料(部分截圖)

想要參與Android進階免費系列直播課
以及獲取Android開發工程師資料包的同學,
點選加入:點選連結加入群聊【Android開發交流】: https://jq.qq.com/?_wv=1027&k=5richpI
免費課程,名額有限,先到先得~~