LocalBroadcastManager 简介
学习Android的同鞋一定知道四大组件,四大组件有:
四大组件中的BroadcastReceiver是全局广播,即发送广播时可能被多个App接收到,有时候从安全角度考虑,为了数据的安全传递,是不是有办法避免被多个App接收广播,于是有了本地广播,本地广播只会在自己的App内传播,用于在同一个应用内的不同组件间发送Broadcast进行通信。使用本地广播,需要用到support库中的LocalBroadcastManager。
LocalBroadcastManager使用
这里先列出LocalBroadcastManager中常用的方法:
LocalBroadcastManager中方法 | 说明 |
---|---|
getInstance(Context context) | 获取本地广播实例 |
registerReceiver(BroadcastReceiver receiver, IntentFilter filter) | 注册广播 |
unregisterReceiver(BroadcastReceiver receiver) | 解注册 |
sendBroadcast(Intent intent) | 发送广播(内部使用Handler,保证onReceive在主线程中调用) |
sendBroadcastSync(Intent intent) | 同步发送广播,如果消息队列中消息太多,会导致广播接收者接收广播太慢,可使用这个方法同步发送广播 |
- 获取LocalBroadcastManager对象
LocalBroadcastManager被设计为一个单例类,通过getInstance
方法获取实例,参数需要一个上下文对象
// java
LocalBroadcastManager localManager= LocalBroadcastManager.getInstance(mContext);
// kotlin
val localManager = LocalBroadcastManager.getInstance(mContext)
- 注册观察者
和全局广播的思想一样,如果要接收广播,那么需要先注册一个广播,才能接收到匹配的广播。本地广播不能通过在AndroidManifest文件中静态声明注册,只能通过动态注册的方法注册,这里注册时需要调用registerReceiver
方法,需要传递两个参数BroadcastReceiver
和IntentFilter
//java
LocalBroadcastManager localManager = LocalBroadcastManager.getInstance(mContext);
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "收到广播", Toast.LENGTH_SHORT).show();
}
};
IntentFilter intentFilter = new IntentFilter("LocalBroadcastManager-test");
localManager.registerReceiver(receiver, intentFilter);//注册广播
//kotlin
val localManager = LocalBroadcastManager.getInstance(mContext)
val broadReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Toast.makeText(context, "收到广播", Toast.LENGTH_SHORT).show()
}
}
val intentFilter = IntentFilter("LocalBroadcastManager-test")
localManager.registerReceiver(broadReceiver, intentFilter)
- 通过本地发送广播
通过上面定义BroadcastReceiver来接收广播处理,现在可以发送广播试试了
//java
localManager.sendBroadcast(new Intent("LocalBroadcastManager-test"));
//kotlin
localManager.sendBroadcast(Intent("LocalBroadcastManager-test"))
LocalBroadcastManager 源码分析
LocalBroadcastManager位于android.support.v4.content包下
因为本地广播基于观察者模式设计,所以将LocalBroadcastManager设计成单例,被观察者只有一个嘛,以下是获取实例和私有构造方法
// 忽略部分代码
public static LocalBroadcastManager getInstance(@NonNull Context context) {
Object var1 = mLock;
synchronized(mLock) {
if (mInstance == null) {
mInstance = new LocalBroadcastManager(context.getApplicationContext());
}
return mInstance;
}
}
private LocalBroadcastManager(Context context) {
this.mAppContext = context;
//UI线程的Looper,说明可以在子线程获取实例、发送广播
this.mHandler = new Handler(context.getMainLooper()) {
public void handleMessage(Message msg) {
switch(msg.what) {
case 1:
LocalBroadcastManager.this.executePendingBroadcasts();
break;
default:
super.handleMessage(msg);
}
}
};
}
在LocalBroadcastManager中有两个内部静态类,封装了BroadcastReceiver和IntentFilter
// 忽略部分代码
private static final class ReceiverRecord {
final IntentFilter filter;//注册广播时的intentFilter
final BroadcastReceiver receiver;//注册广播时的broadcastReceiver
boolean broadcasting;//是否添加到广播队列
boolean dead;//死亡标识
ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) {
this.filter = _filter;
this.receiver = _receiver;
}
public String toString() {
StringBuilder builder = new StringBuilder(128);
builder.append("Receiver{");
builder.append(this.receiver);
builder.append(" filter=");
builder.append(this.filter);
if (this.dead) {
builder.append(" DEAD");
}
builder.append("}");
return builder.toString();
}
}
private static final class BroadcastRecord {
final Intent intent;//发送广播的intent
final ArrayList<LocalBroadcastManager.ReceiverRecord> receivers;//发送广播intent匹配的receivers
BroadcastRecord(Intent _intent, ArrayList<LocalBroadcastManager.ReceiverRecord> _receivers) {
this.intent = _intent;
this.receivers = _receivers;
}
}
下面看下注册观察都和解注册的代码
// 保存所有注册BroadcastReceiver的HashMap
private final HashMap<BroadcastReceiver, ArrayList<LocalBroadcastManager.ReceiverRecord>> mReceivers = new HashMap();
//保存所有注册BroadcastReceiver中IntentFilter的action
private final HashMap<String, ArrayList<LocalBroadcastManager.ReceiverRecord>> mActions = new HashMap();
public void registerReceiver(@NonNull BroadcastReceiver receiver, @NonNull IntentFilter filter) {
HashMap var3 = this.mReceivers;
synchronized(this.mReceivers) {
// 创建一个LocalBroadcastManager.ReceiverRecord对象
LocalBroadcastManager.ReceiverRecord entry = new LocalBroadcastManager.ReceiverRecord(filter, receiver);
// 从mReceivers中获取是否存在的LocalBroadcastManager.ReceiverRecord对象
ArrayList<LocalBroadcastManager.ReceiverRecord> filters = (ArrayList)this.mReceivers.get(receiver);
if (filters == null) {
//如果mReceivers不存在要注册的receiver,则创建一个新的,保存到Mreceivers中
filters = new ArrayList(1);
this.mReceivers.put(receiver, filters);//保存receiver对应的LocalBroadcastManager.ReceiverRecord
}
filters.add(entry);
for(int i = 0; i < filter.countActions(); ++i) {
// 遍历获取filter中所有的action,保存到mActions中
String action = filter.getAction(i);
ArrayList<LocalBroadcastManager.ReceiverRecord> entries = (ArrayList)this.mActions.get(action);
if (entries == null) {
entries = new ArrayList(1);
this.mActions.put(action, entries);//保存action对应的LocalBroadcastManager.ReceiverRecord
}
entries.add(entry);
}
}
}
public void unregisterReceiver(@NonNull BroadcastReceiver receiver) {
HashMap var2 = this.mReceivers;
synchronized(this.mReceivers) {
//mReceivers中移除已注册的receiver
ArrayList<LocalBroadcastManager.ReceiverRecord> filters = (ArrayList)this.mReceivers.remove(receiver);
if (filters != null) {//移除成功不为null
for(int i = filters.size() - 1; i >= 0; --i) {
LocalBroadcastManager.ReceiverRecord filter = (LocalBroadcastManager.ReceiverRecord)filters.get(i);
filter.dead = true;//死亡标识
for(int j = 0; j < filter.filter.countActions(); ++j) {
String action = filter.filter.getAction(j);
ArrayList<LocalBroadcastManager.ReceiverRecord> receivers = (ArrayList)this.mActions.get(action);
if (receivers != null) {
for(int k = receivers.size() - 1; k >= 0; --k) {
LocalBroadcastManager.ReceiverRecord rec = (LocalBroadcastManager.ReceiverRecord)receivers.get(k);
if (rec.receiver == receiver) {
rec.dead = true;//标识死亡
receivers.remove(k);//先移除mAction中action对应List中的
}
}
if (receivers.size() <= 0) {
this.mActions.remove(action);//如果action对应的list为0,移除mAction中的action
}
}
}
}
}
}
}
发送广播的逻辑
public boolean sendBroadcast(@NonNull Intent intent) {
HashMap var2 = this.mReceivers;
synchronized(this.mReceivers) {
String action = intent.getAction();
String type = intent.resolveTypeIfNeeded(this.mAppContext.getContentResolver());
Uri data = intent.getData();
String scheme = intent.getScheme();
Set<String> categories = intent.getCategories();
boolean debug = (intent.getFlags() & 8) != 0;
if (debug) {
Log.v("LocalBroadcastManager", "Resolving type " + type + " scheme " + scheme + " of intent " + intent);
}
// 获取匹配的action的ReceiverRecord对象
ArrayList<LocalBroadcastManager.ReceiverRecord> entries = (ArrayList)this.mActions.get(intent.getAction());
if (entries != null) {
if (debug) {
Log.v("LocalBroadcastManager", "Action list: " + entries);
}
ArrayList<LocalBroadcastManager.ReceiverRecord> receivers = null;
int i;
//遍历匹配到action的广播
for(i = 0; i < entries.size(); ++i) {
LocalBroadcastManager.ReceiverRecord receiver = (LocalBroadcastManager.ReceiverRecord)entries.get(i);
if (debug) {
Log.v("LocalBroadcastManager", "Matching against filter " + receiver.filter);
}
if (receiver.broadcasting) {
if (debug) {
Log.v("LocalBroadcastManager", " Filter's target already added");
}
} else {
int match = receiver.filter.match(action, type, scheme, data, categories, "LocalBroadcastManager");
if (match >= 0) {
if (debug) {
Log.v("LocalBroadcastManager", " Filter matched! match=0x" + Integer.toHexString(match));
}
if (receivers == null) {
receivers = new ArrayList();
}
receivers.add(receiver);
receiver.broadcasting = true;
} else if (debug) {
String reason;
switch(match) {
case -4:
reason = "category";
break;
case -3:
reason = "action";
break;
case -2:
reason = "data";
break;
case -1:
reason = "type";
break;
default:
reason = "unknown reason";
}
Log.v("LocalBroadcastManager", " Filter did not match: " + reason);
}
}
}
if (receivers != null) {
for(i = 0; i < receivers.size(); ++i) {
((LocalBroadcastManager.ReceiverRecord)receivers.get(i)).broadcasting = false;
}
// 添加到广播队列
this.mPendingBroadcasts.add(new LocalBroadcastManager.BroadcastRecord(intent, receivers));
if (!this.mHandler.hasMessages(1)) {
//发送消息
this.mHandler.sendEmptyMessage(1);
}
return true;
}
}
return false;
}
}
sendBroadcastSync方法有些不同,可自行查看源码
下面来看下处理广播的逻辑
void executePendingBroadcasts() {
while(true) {
HashMap var2 = this.mReceivers;
LocalBroadcastManager.BroadcastRecord[] brs;
synchronized(this.mReceivers) {
int N = this.mPendingBroadcasts.size();
if (N <= 0) {
return;
}
brs = new LocalBroadcastManager.BroadcastRecord[N];
this.mPendingBroadcasts.toArray(brs); //转换array
this.mPendingBroadcasts.clear();//清空操作
}
for(int i = 0; i < brs.length; ++i) {
LocalBroadcastManager.BroadcastRecord br = brs[i];
int nbr = br.receivers.size();
// 遍历回调onReceiver方法
for(int j = 0; j < nbr; ++j) {
LocalBroadcastManager.ReceiverRecord rec = (LocalBroadcastManager.ReceiverRecord)br.receivers.get(j);
if (!rec.dead) {//如果没有dead调用onReceiver方法
rec.receiver.onReceive(this.mAppContext, br.intent);
}
}
}
}
}
到这里就把整个逻辑分析了,主要逻辑有:
- 在LocalBroadcastManager中通过
registerReceiver
中注册广播,保存到mReceivers
和mActions
中 - 通过
sendBroadcast
中匹配mActions
中的BroadcastReceiver,将匹配到的对象保存到mPendingBroadcasts
中 - 最终调用
executePendingBroadcasts
来发送广播