简介
本地广播:发送的广播事件不被其他应用程序获取,也不能响应其他应用程序发送的广播事件。本地广播只能被动态注册,不能静态注册。动态注册或方法时需要用到LocalBroadcastManager。
本地广播使用的是观察者模式
本地广播的基本使用
- 注册广播
localBroadcast = new LocalBroadcast();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.wuyazhou.test");
LocalBroadcastManager.getInstance(this).registerReceiver(localBroadcast, intentFilter);
- 解注册广播
LocalBroadcastManager.getInstance(this).unregisterReceiver(localBroadcast);
- 发送广播
LocalBroadcastManager.getInstance(BroadcastActivity.this).sendBroadcast(new Intent("com.wuyazhou.test"));
本地广播的实现原理
通过本地广播的基本使用知道本地广播和全局广播在形式上主要的不同源于LocalBroadcastManager这个类。
1. 实例化本地广播管理者LocalBroadcastManager.getInstance(this)
/*单例模式,进程中维持一份数据*/
private static LocalBroadcastManager mInstance;
public static LocalBroadcastManager getInstance(Context context) {
synchronized (mLock) {
if (mInstance == null) {
mInstance = new LocalBroadcastManager(context.getApplicationContext());
}
return mInstance;
}
}
private LocalBroadcastManager(Context context) {
//初始化环境
mAppContext = context;
//通过主线程的Looper构造的Handler
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);
}
}
};
}
2. LocalBroadcastManager类的两个内部数据类(ReceiverRecord 和 BroadcastRecord )和三个数据集合。
private static final class ReceiverRecord {
//记录当前意图过滤
final IntentFilter filter;
//记录当前广播接收器
final BroadcastReceiver receiver;
//是否正在广播
boolean broadcasting;
//是否挂掉
boolean dead;
ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) {
filter = _filter;
receiver = _receiver;
}
}
private static final class BroadcastRecord {
//记录当前意图
final Intent intent;
//记录符合当前意图的ReceivedRecord数据结构
final ArrayList<ReceiverRecord> receivers;
BroadcastRecord(Intent _intent, ArrayList<ReceiverRecord> _receivers) {
intent = _intent;
receivers = _receivers;
}
}
//记录当前注册所有广播
private final HashMap<BroadcastReceiver, ArrayList<ReceiverRecord>> mReceivers= new HashMap<>();
//记录当前拥有某Action的广播
private final HashMap<String, ArrayList<ReceiverRecord>> mActions = new HashMap<>();
//记录当前等待执行的广播
private final ArrayList<BroadcastRecord> mPendingBroadcasts = new ArrayList<>();
3. 注册广播LocalBroadcastManager.getInstance(this)
.registerReceiver(localBroadcast, intentFilter);
public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
synchronized (mReceivers) {
/*将广播接收者和对应的意图过滤匹配起来,注意:一个广播接受者可能有多个意图过滤。*/
ReceiverRecord entry = new ReceiverRecord(filter, receiver);
ArrayList<ReceiverRecord> filters = mReceivers.get(receiver);
if (filters == null) {
filters = new ArrayList<>(1);
mReceivers.put(receiver, filters);
}
filters.add(entry);
//将意图过滤中的Action和对应得广播接受者对应起来,注意:一个Action可能对应多个广播接受者
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);
}
}
}
4. 解注册广播LocalBroadcastManager.getInstance(this)
.unregisterReceiver(localBroadcast);
public void unregisterReceiver(BroadcastReceiver receiver) {
synchronized (mReceivers) {
//删除指定广播,并返回指定广播对应的所有意图过滤。
final ArrayList<ReceiverRecord> filters = mReceivers.remove(receiver);
if (filters == null) {
return;
}
/*遍历指定广播的所有意图过滤*/
for (int i=filters.size()-1; i>=0; i--) {
final ReceiverRecord filter = filters.get(i);
//标记当前广播挂掉
filter.dead = true;
/*遍历过滤意图的所有Action*/
for (int j=0; j<filter.filter.countActions(); j++) {
final String action = filter.filter.getAction(j);
/*根据Action遍历mAction列表*/
final ArrayList<ReceiverRecord> receivers = mActions.get(action);
if (receivers != null) {
for (int k=receivers.size()-1; k>=0; k--) {
final ReceiverRecord rec = receivers.get(k);
/*mAction列表中如果有指定广播要删除,并标记mAction列表中的该广播挂掉*/
if (rec.receiver == receiver) {
rec.dead = true;
receivers.remove(k);
}
}
if (receivers.size() <= 0) {
mActions.remove(action);
}
}
}
}
}
}
5. 发送广播LocalBroadcastManager.getInstance(BroadcastActivity.this)
.sendBroadcast(new Intent(“com.wuyazhou.test”));
public boolean sendBroadcast(Intent intent) {
synchronized (mReceivers) {
/*获取意图中的过滤信息*/
final String action = intent.getAction(); //行为 Action
final String type = intent.resolveTypeIfNeeded( //类型 Type
mAppContext.getContentResolver());
final Uri data = intent.getData(); //URI
final String scheme = intent.getScheme(); //scheme
final Set<String> categories = intent.getCategories(); // 种类
//根据意图中的Action获取mAction列表中所有的广播接收者
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;
}
/*将符合意图的广播接受者和意图通过BroadcastRecord类对应起来,然后通过Handle发送*/
mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
}
return true;
}
}
}
return false;
}
6. 最后通过在构造方法中构建的主线程Handler发送消息 执行executePendingBroadcasts()该方法
/*执行等待的广播发送*/
private void executePendingBroadcasts() {
for (int j=0; j<nbr; j++) {
final ReceiverRecord rec = br.receivers.get(j);
if (!rec.dead) {
rec.receiver.onReceive(mAppContext, br.intent);
}
}
}