LocalBroadcastManager
本地广播,用于应用内部通信,可以实现线程间交互。
标准的广播 BroadcastReceiver
用于跨进程通信,不同应用之间的通信,实现原理基于 Binder
机制。而同一个应用相同进程内,通过观察者模式来实现消息传递,并不需要全局广播,在 support.v4
包中提供的 LocalBroadcastManager
就是用来实现本地广播的,它是基于 Handler
机制,实现线程间通信,Handler.mLooper
为应用的主线程 Looper
。LocalBroadcastManager
本地广播通过 Handler
逐条处理广播的(串行处理方式),它支持异步和同步处理方式。
内部类
ReceiverRecord
广播接收器记录
ReceiverRecord
类存储了一个广播接收器,及其对应的过滤器。
BroadcastReceiver receiver
:注册的广播接收器IntentFilter filter
:注册广播接收器时对应过滤器broadcasting
:表示是否正在处理对应的广播,避免重复处理
1 | private static class ReceiverRecord { |
BroadcastRecord
广播发送记录
ReceiverRecord
类存储了一个广播 Intent
,及其匹配的所有广播接收器记录列表。
Intent intent
:记录发送的广播ArrayList<ReceiverRecord> receivers
:匹配该广播的所有接收器列表
1 | private static class BroadcastRecord { |
成员变量和构造方法
源码列表
1 | // Application Context |
重要成员变量
mAppContext
:整个应用的Context
,避免组件退出引起内存泄露mReceivers
:哈希表,存储应用所有的广播接收器,及每个广播接收器对应的广播过滤器列表(一个广播接收器可以监听多个广播)mActions
:哈希表,存储应用所有的广播,及每条广播对应的广播接收器列表(一个广播可以有多个广播接收器响应)mPendingBroadcasts
:数组列表,记录需要处理广播mHandler
:使用Handler
通信机制来处理应用内部的所有本地广播,Looper
对应的是应用主线程Looper
单例模式
LocalBroadcastManager
的构造方法是私有的,使用单例模式来获取实例。构造方法中,实例化 Handler
并实现消息处理方法。(这里单例模式更推荐双检锁实现方式)
注册/取消注册广播
注册广播
注册广播的过程,就是一个数据存储过程。
- 根据注册的广播接收器和过滤器,新建
ReceiverRecord
对象 - 将广播接收器和过滤器,存储到
mReceivers
中 - 将广播过滤器的
Action
存储到mActions
中,方便后续根据Action
查找对应的广播接收器
1 | public void registerReceiver(BroadcastReceiver receiver, |
取消广播注册
取消广播注册,就是一个移除数据的过程。
- 从
mReceivers
中移除该广播接收器 - 从
mActions
中移除该广播接收器监听的广播过滤器列表中每个Action
1 | public void unregisterReceiver(BroadcastReceiver receiver) { |
发送广播
发送广播
广播的发送有两种:同步和异步发送;异步发送是通过 Handler.sendEmptyMessage
实现,而同步则是在异步的基础上,马上执行广播接收器响应(主要是在异步出现阻塞或者之前有过多任务时,才能体现出明显的效率)。
- 从
mActions
中查找广播对应的广播接收记录列表 - 每个广播接收记录中,如果不是正在被广播,则添加到
mPendingBroadcasts
中 Handler
发送消息,异步执行
1 | public boolean sendBroadcast(Intent intent) { |
sendBroadcastSync
同步广播,如果有广播在排队处理,直接调用广播执行方法 executePendingBroadcasts
;如果广播队列并没有等待,效率区别不大。
响应广播
不管是同步广播还是异步广播,最终响应执行都是调用 executePendingBroadcasts
方法。主要功能是:从 mPendingBroadcasts
中逐个取出广播接收器,响应 BroadcastReceiver.onReceive
回调方法。
1 | private void executePendingBroadcasts() { |
示例
在 Activity
中注册一个广播接收器,在 Services
后台线程中发送本地广播,形成线程间本地广播通信。
广播注册/取消注册
1 | // LocalBroadcastActivity.java |
广播发送
1 | // LocalBroadcastService.java |
小结
本地广播的三个特点:
- 数据只会在当前应用中广播,不会传递到其他应用(甚至当前应用的其他进程),确保数据安全
- 其他应用的广播不会发送到当前应用中,不用担心安全漏洞
- 不用通过系统
AMS
全局管理广播,而是本地保存数据,广播更高效
另外:本地广播只支持动态注册的方式。