LocalBroadcastManager 本地广播,用于应用内部通信,可以实现线程间交互。  
标准的广播 BroadcastReceiver 用于跨进程通信,不同应用之间的通信,实现原理基于 Binder 机制。而同一个应用相同进程内,通过观察者模式来实现消息传递,并不需要全局广播,在 support.v4 包中提供的 LocalBroadcastManager 就是用来实现本地广播的,它是基于 Handler 机制,实现线程间通信,Handler.mLooper 为应用的主线程 Looper 。
LocalBroadcastManager 本地广播通过 Handler 逐条处理广播的(串行处理方式),它支持异步和同步处理方式。  
内部类
ReceiverRecord 广播接收器记录
ReceiverRecord 类存储了一个广播接收器,及其对应的过滤器。  
BroadcastReceiver receiver :注册的广播接收器   
IntentFilter filter :注册广播接收器时对应过滤器   
broadcasting :表示是否正在处理对应的广播,避免重复处理   
1 2 3 4 5 6 7 8 9 10 11 12 13
   | private static class ReceiverRecord {     final IntentFilter filter;     final BroadcastReceiver receiver;     boolean broadcasting;
      ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver){         filter = _filter;         receiver = _receiver;     }
      @Override     public String toString() {...} }
  | 
 
BroadcastRecord 广播发送记录
ReceiverRecord 类存储了一个广播 Intent ,及其匹配的所有广播接收器记录列表。  
Intent intent :记录发送的广播   
ArrayList<ReceiverRecord> receivers :匹配该广播的所有接收器列表   
1 2 3 4 5 6 7 8 9
   | private static class BroadcastRecord {     final Intent intent;     final ArrayList<ReceiverRecord> receivers;
      BroadcastRecord(Intent _intent, ArrayList<ReceiverRecord> _receivers){         intent = _intent;         receivers = _receivers;     } }
  | 
 
成员变量和构造方法
源码列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
   |  private final Context mAppContext;
  private final HashMap<BroadcastReceiver,ArrayList<IntentFilter>> mReceivers         = new HashMap<BroadcastReceiver, ArrayList<IntentFilter>>();
  private final HashMap<String, ArrayList<ReceiverRecord>> mActions         = new HashMap<String, ArrayList<ReceiverRecord>>();
  private final ArrayList<BroadcastRecord> mPendingBroadcasts         = new ArrayList<BroadcastRecord>();
  static final int MSG_EXEC_PENDING_BROADCASTS = 1;
  private final Handler mHandler;
 
  private static final Object mLock = new Object(); private static LocalBroadcastManager mInstance;
  public static LocalBroadcastManager getInstance(Context context) {     synchronized (mLock) {         if (mInstance == null) {             整个应用的 Context             mInstance = new LocalBroadcastManager(                 context.getApplicationContext());         }         return mInstance;     } }
  private LocalBroadcastManager(Context context) {     mAppContext = context;          mHandler = new Handler(context.getMainLooper()) {
          @Override         public void handleMessage(Message msg) {             switch (msg.what) {                 case MSG_EXEC_PENDING_BROADCASTS:                     executePendingBroadcasts();                     break;                 default:                     super.handleMessage(msg);             }         }     }; }
 
  | 
 
重要成员变量
mAppContext :整个应用的 Context ,避免组件退出引起内存泄露   
mReceivers :哈希表,存储应用所有的广播接收器,及每个广播接收器对应的广播过滤器列表(一个广播接收器可以监听多个广播)   
mActions :哈希表,存储应用所有的广播,及每条广播对应的广播接收器列表(一个广播可以有多个广播接收器响应)   
mPendingBroadcasts :数组列表,记录需要处理广播   
mHandler :使用 Handler 通信机制来处理应用内部的所有本地广播,Looper 对应的是应用主线程 Looper   
单例模式
LocalBroadcastManager 的构造方法是私有的,使用单例模式来获取实例。构造方法中,实例化 Handler 并实现消息处理方法。(这里单例模式更推荐双检锁实现方式)  
注册/取消注册广播
注册广播
注册广播的过程,就是一个数据存储过程。  
- 根据注册的广播接收器和过滤器,新建 
ReceiverRecord 对象   
- 将广播接收器和过滤器,存储到 
mReceivers 中   
- 将广播过滤器的 
Action 存储到 mActions 中,方便后续根据 Action 查找对应的广播接收器   
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   | public void registerReceiver(BroadcastReceiver receiver,          IntentFilter filter) {     synchronized (mReceivers) {         ReceiverRecord entry = new ReceiverRecord(filter, receiver);         ArrayList<IntentFilter> filters = mReceivers.get(receiver);         if (filters == null) {             filters = new ArrayList<IntentFilter>(1);             mReceivers.put(receiver, filters);         }         filters.add(filter);         for (int i=0; i<filter.countActions(); i++) {             String action = filter.getAction(i);             ArrayList<ReceiverRecord> entries = mActions.get(action);             if (entries == null) {                 entries = new ArrayList<ReceiverRecord>(1);                 mActions.put(action, entries);             }             entries.add(entry);         }     } }
   | 
 
取消广播注册
取消广播注册,就是一个移除数据的过程。  
- 从 
mReceivers 中移除该广播接收器   
- 从 
mActions 中移除该广播接收器监听的广播过滤器列表中每个 Action   
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   | public void unregisterReceiver(BroadcastReceiver receiver) {     synchronized (mReceivers) {         ArrayList<IntentFilter> filters = mReceivers.remove(receiver);         if (filters == null) {             return;         }         for (int i=0; i<filters.size(); i++) {             IntentFilter filter = filters.get(i);             for (int j=0; j<filter.countActions(); j++) {                 String action = filter.getAction(j);                 ArrayList<ReceiverRecord> receivers=mActions.get(action);                 if (receivers != null) {                     for (int k=0; k<receivers.size(); k++) {                         if (receivers.get(k).receiver == receiver) {                             receivers.remove(k);                             k--;                         }                     }                     if (receivers.size() <= 0) {                         mActions.remove(action);                     }                 }             }         }     } }
  | 
 
发送广播
发送广播
广播的发送有两种:同步和异步发送;异步发送是通过 Handler.sendEmptyMessage 实现,而同步则是在异步的基础上,马上执行广播接收器响应(主要是在异步出现阻塞或者之前有过多任务时,才能体现出明显的效率)。  
- 从 
mActions 中查找广播对应的广播接收记录列表   
- 每个广播接收记录中,如果不是正在被广播,则添加到 
mPendingBroadcasts 中   
Handler 发送消息,异步执行   
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
   | public boolean sendBroadcast(Intent intent) {     synchronized (mReceivers) {         final String action = intent.getAction();         final String type = intent.resolveTypeIfNeeded(                 mAppContext.getContentResolver());         final Uri data = intent.getData();         final String scheme = intent.getScheme();         final Set<String> categories = intent.getCategories();         ...         ArrayList<ReceiverRecord> entries=mActions.get(intent.getAction());         if (entries != null) {             ...             ArrayList<ReceiverRecord> receivers = null;             for (int i=0; i<entries.size(); i++) {                 ReceiverRecord receiver = entries.get(i);                 ...                 if (receiver.broadcasting) {                     ...                     continue;                 }
                  int match = receiver.filter.match(action, type, scheme,                          data, categories, "LocalBroadcastManager");                 if (match >= 0) {                     ...                     if (receivers == null) {                         receivers = new ArrayList<ReceiverRecord>();                     }                     receivers.add(receiver);                     receiver.broadcasting = true;                 } else {                     ...                 }             }
              if (receivers != null) {               for (int i=0; i<receivers.size(); i++) {                   receivers.get(i).broadcasting = false;               }               mPendingBroadcasts.add(new BroadcastRecord(intent,receivers));               if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {                   mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);               }               return true;             }         }     }     return false; }
  public void sendBroadcastSync(Intent intent) {     if (sendBroadcast(intent)) {         executePendingBroadcasts();     } }
  | 
 
sendBroadcastSync 同步广播,如果有广播在排队处理,直接调用广播执行方法 executePendingBroadcasts ;如果广播队列并没有等待,效率区别不大。  
响应广播
不管是同步广播还是异步广播,最终响应执行都是调用 executePendingBroadcasts 方法。主要功能是:从 mPendingBroadcasts 中逐个取出广播接收器,响应 BroadcastReceiver.onReceive 回调方法。  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   | private void executePendingBroadcasts() {     while (true) {         BroadcastRecord[] brs = null;         synchronized (mReceivers) {             final int N = mPendingBroadcasts.size();             if (N <= 0) {                 return;             }             brs = new BroadcastRecord[N];             mPendingBroadcasts.toArray(brs);             mPendingBroadcasts.clear();         }         for (int i=0; i<brs.length; i++) {             BroadcastRecord br = brs[i];             for (int j=0; j<br.receivers.size(); j++) {                 br.receivers.get(j).receiver.                     onReceive(mAppContext, br.intent);             }         }     } }
  | 
 
示例
在 Activity 中注册一个广播接收器,在 Services 后台线程中发送本地广播,形成线程间本地广播通信。  
广播注册/取消注册
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
   | 
  private LocalBroadcastManager mLocalBroadcastManager = null; private boolean mRegistered; private BroadcastReceiver mReceiver = new BroadcastReceiver() {     @Override     public void onReceive(Context context, Intent intent) {         if (intent != null){             String response = intent.getStringExtra("key");             Log.d(TAG, "onReceive: response: " + response);         }     } };
  @Override protected void onCreate(Bundle savedInstanceState) {     super.onCreate(savedInstanceState);     setContentView(R.layout.activity_local_broadcast);     mLocalBroadcastManager =             LocalBroadcastManager.getInstance(this); }
  @Override protected void onStart() {     super.onStart();     IntentFilter intentFilter = new IntentFilter(ACTION_RESPONSE);     mLocalBroadcastManager.registerReceiver(mReceiver, intentFilter);     mRegistered = true; }
  @Override protected void onStop() {     super.onStop();     if (mRegistered){         mRegistered = false;         mLocalBroadcastManager.unregisterReceiver(mReceiver);         Log.d(TAG, "onStop: mLocalBroadcastManager.unregisterReceiver");     } }
 
  | 
 
广播发送
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   |  private void doLongWork(final String value){     new Thread(new Runnable() {         @Override         public void run() {             Log.d(TAG, "run: sleep...");             try {                 Thread.sleep(2000);             } catch (InterruptedException e) {                 e.printStackTrace();             }             Intent intent = new Intent(ACTION_RESPONSE);             intent.putExtra("key", "response");             LocalBroadcastManager.getInstance(this).sendBroadcast(intent);         }     }).start(); }
 
  | 
 
小结
本地广播的三个特点:  
- 数据只会在当前应用中广播,不会传递到其他应用(甚至当前应用的其他进程),确保数据安全  
 
- 其他应用的广播不会发送到当前应用中,不用担心安全漏洞  
 
- 不用通过系统 
AMS 全局管理广播,而是本地保存数据,广播更高效   
另外:本地广播只支持动态注册的方式。  
参考文档