源码分析:
1:getInstance(this);用了标准的单利模式;
2:构造中初始化了一个Handle对象,用于对广播的分发;
3:广播的注册、反注册、发送流程
如果让我们来自己来实现广播的注册、反注册、发送我们会怎么搞呢?
首先,注册的时候需要提供BroadcastReceiver和对应的IntentFilter,我们可以对这种数据结构进行封装,放到一个类中ReceiverRecord。
然后维护一个ReceiverRecord对象列表,用于记录当前注册了哪些BroadcastReceiver。可以简单使用ArrayList.
在unRegister的时候根据提供的BroadcastReceiver对象,遍历List找出对应的receiver进行移除。
这样每来一个unRegister我们都需要对Receiver列表做一次遍历,开销有点大,在查操作比较多的时候我们可以使用MAP。
HashMap
ReceiverRecord中已经包含BroadcastReceiver对象了,所以value直接使用IntentFilte就行了,简化数据结构。
那如果一个Receiver注册了多个IntentFilter呢?比如说一个receiver对象注册两次传入不同的IntentFilter.所以Value需要改造为ArrayList。 最终用于维护当前Reciver对象列表的数据结构是这样事儿的:
HashMap> mReceivers.
当删除时可以通过receiver对象为key在map中快速查找并移除。
发送广播的时候呢?我们知道sendBroadcast时只传入了Intent对象,Intent携带了Action用于和已经注册的receiver匹配。在查找receiver时,需要对
HashMap> mReceivers 的Value进行遍历,每一个Value ArrayList 又需要遍历一次。这个查找的开销实在太大了。
看来我们为了实现Action和receiver的快速匹配需要再维护一个数据结构了。同样是频繁查找的需求使用HashMap.
将Action作为Key,value肯定是与之匹配的receiver了。因为一个Action可能会对应多个receiver,receiver注册的时候可以使用相同的Action.所以value需要使用ArrayList. 当发送广播时可以快速根据Action找到对应的receiver。对了,不仅仅要使用Action匹配,filter中还有其他信息匹配成功之后才能确认是真正的receiver.所以需要使用ReceiverRecord作为value,因为不仅包含了receiver对象,同时包含了IntentFilter.所以最终的数据结构是
HashMap>.
我们来看Google是怎么实现的呢?
先来看两个内部类:
//内部类ReceiverRecord Receiver记录:用于记录reciver,对应的IntentFilter和是否在broadcast状态
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() {
StringBuilder builder = new StringBuilder(128);
builder.append("Receiver{");
builder.append(receiver);
builder.append(" filter=");
builder.append(filter);
builder.append("}");
return builder.toString();
}
}
//BroadcastRecord 广播记录:用于记录广播的intent以及有哪些对应的ReceiverRecord
private static class BroadcastRecord {
final Intent intent;
final ArrayList receivers;
BroadcastRecord(Intent _intent, ArrayList _receivers) {
intent = _intent;
receivers = _receivers;
}
}
再来看几个成员变量:
//维护一个mReceivers Map 记录一个所有的receiver,每一个对应哪些Intentfilters。主要用于记录当前有哪些receiver需要维护接受广播。 //方便广播的反注册,反注册时可以快速找到filter从而找到Action,从而操作mAction.试想如果没有mReceivers,只能全部遍历mAction找出所有BroadcastRecord,从而找到filter和Action,性能很差。 private final HashMap> mReceivers = new HashMap>(); //维护一个mActions Map 记录所有的Action,每一个对应哪些ReceiverRecord private final HashMap> mActions = new HashMap>(); //维护一个List,记录当前正处在等待状态的广播BroadcastRecord,通过BroadcastRecord可以找到intent对应的receivers private final ArrayList mPendingBroadcasts = new ArrayList();
广播的发送过程
/**
* Register a receive for any local broadcasts that match the given IntentFilter.
*
* @param receiver The BroadcastReceiver to handle the broadcast.
* @param filter Selects the Intent broadcasts to be received.
*
* @see #unregisterReceiver
*/
public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
synchronized (mReceivers) {
ReceiverRecord entry = new ReceiverRecord(filter, receiver);
//查找receiver有没有在mReceiver记录中,如果不在需要添加进去。
ArrayList filters = mReceivers.get(receiver);
if (filters == null) {
filters = new ArrayList(1);
mReceivers.put(receiver, filters);
}
//将IntentFilter加入receiver对应的匹配规则中。filters为mReceivers map的value,类型是IntentFilter的ArrayList。
//同一个receiver可能有多个IntentFilter。mReceivers就记录了所有的receiver,并且指明每一个receiver所能匹配到的IntentFilter.
filters.add(filter);
//开始遍历IntentFilter中的Action.检查Action是否在mActions,如果不在不要添加进去。
//mActions是Action为Key , ArrayList为value的MAP。
//记录了当前有那些Action,并且每个Action对应的Receiver(ReceiverRecord)是哪个。
for (int i=0; i entries = mActions.get(action);
if (entries == null) {
entries = new ArrayList(1);
mActions.put(action, entries);
}
//将ReceiverRcoder对象加入entries:entries是该Action对应的ReceiverRecord列表。
entries.add(entry);
}
}
}
广播的反注册过程
/**
* Unregister a previously registered BroadcastReceiver. All
* filters that have been registered for this BroadcastReceiver will be
* removed.
*
* @param receiver The BroadcastReceiver to unregister.
*
* @see #registerReceiver
*/
public void unregisterReceiver(BroadcastReceiver receiver) {
synchronized (mReceivers) {
//在Receiver列表中移除要注销的receiver,返回对应的filters.
ArrayList filters = mReceivers.remove(receiver);
if (filters == null) {
return;
}
//在Action Map中移除对应的receiver
for (int i=0; i receivers = mActions.get(action);
if (receivers != null) {
for (int k=0; k categories = intent.getCategories();
final boolean debug = DEBUG ||
((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
if (debug) Log.v(
TAG, "Resolving type " + type + " scheme " + scheme
+ " of intent " + intent);
//根据Action从mActions MAP 中取对应的receivers.
ArrayList entries = mActions.get(intent.getAction());
if (entries != null) {
if (debug) Log.v(TAG, "Action list: " + entries);
ArrayList receivers = null;
//遍历receivers找出符合IntentFilter条件的
for (int i=0; i= 0) {
if (debug) Log.v(TAG, " Filter matched! match=0x" +
Integer.toHexString(match));
if (receivers == null) {
receivers = new ArrayList();
}
receivers.add(receiver);
//将receiver 是否在分发中置位true
receiver.broadcasting = true;
} else {
if (debug) {
String reason;
switch (match) {
case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
default: reason = "unknown reason"; break;
}
Log.v(TAG, " Filter did not match: " + reason);
}
}
}
//将broadcasting置位false 加入mPendingBroadcasts等待队列中.
if (receivers != null) {
for (int i=0; i
总结
1.LocalBroadcast是APP内部维护的一套广播机制,有很高的安全性和高效性。
所以如果有APP内部发送、接收广播的需要应该使用LocalBroadcast。
2.Receiver只允许动态注册,不允许在Manifest中注册。
3.LocalBroadcastManager所发送的广播action,只能与注册到LocalBroadcastManager中BroadcastReceiver产生互动。