https://www.jianshu.com/p/ca3d87a4cdf3
LocalBroadcastManager 实现原理
LocalBroadcastManager采用的是Handler的消息机制来处理的广播,而注册到系统中的是通过Binder机制实现的,速度是应用内广播要快很多。不过由于Handler的消息机制是为了同一个进程的多线程间进行通信的,因而跨进程时无法使用应用内广播。
初始化
LocalBroadcastManager 采用的是单例模式,并且在私有的构造函数中创建了一个mHandler,该Handler关联的是主线程的Looper。所以消息的处理都是在主线程中处理的。
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) {
mInstance = new LocalBroadcastManager(context.getApplicationContext());
}
return mInstance;
}
}
private LocalBroadcastManager(Context context) {
mAppContext = context;
//mHandler是主线程的
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);
}
}
};
}
注册广播registerReceiver
/**
* 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(@NonNull BroadcastReceiver receiver,
@NonNull 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);
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);
}
}
}
会将 Receiver 和action 存在下方的数据结构中
private final HashMap<BroadcastReceiver, ArrayList<ReceiverRecord>> mReceivers
= new HashMap<>();
private final HashMap<String, ArrayList<ReceiverRecord>> mActions = new HashMap<>();
unregisterReceiver
/**
* Unregister a previously registered BroadcastReceiver. <em>All</em>
* filters that have been registered for this BroadcastReceiver will be
* removed.
*
* @param receiver The BroadcastReceiver to unregister.
*
* @see #registerReceiver
*/
public void unregisterReceiver(@NonNull 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;
for (int j=0; j<filter.filter.countActions(); j++) {
final String action = filter.filter.getAction(j);
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);
if (rec.receiver == receiver) {
rec.dead = true;
receivers.remove(k);
}
}
if (receivers.size() <= 0) {
mActions.remove(action);
}
}
}
}
}
}
总结
优点:
1:相对于串行广播,更加安全,数据只会在应用内部传输,并且限定在同一进程中,一个APK中其他的进程也是不行的
2:性能较好:相对于串行广播,其不对system_server造成任何的性能问题,并且也没有跨进程调用带来的耗时问题
缺点:
1:不支持跨进程,如果跨进程必须考虑其他实现方式
2:不支持静态xml的方式注册,无法实现监听诸如系统开机广播等