LocalBroadcastManager 相信有不少人会有点认生,他是android.support.v4中的一个类,本地广播,只在App内部传播,大家熟知的广播,BrocastReceiver是全局广播,可以跨进程通信,而LocalBroadcastManager,只是作为一个本地消息和数据传输的手段,当然,还是有不少人再用EventBus这类的消息事件库,不过我不喜欢用第三方的库,虽然EventBus也比较小,之前一直在使用BrocastReceiver,也比较随意,后来接触的项目多了,很多事情就需要考虑到了。
使用LocalBroadcastManager的好处:
- 1.只能传输在App内部,不会被其他App接收,确保数据安全
- 2.接收不到其他App广播,免干扰
- 3.比BrocastReceiver更加高效
不过要注意的是,LocalBroadcastManager不能静态注册,只能动态注册,这一特性也反应了第二点,不需要接收其他App的广播,那么我们来看下如何使用吧:
private LocalBroadcastManager lm;
private TestReceiver testReceiver;
private void initReceiver() {
//获取实例
lm = LocalBroadcastManager.getInstance(this);
IntentFilter intentFilter = new IntentFilter("com.android.Test");
testReceiver = new TestReceiver();
//绑定
lm.registerReceiver(testReceiver,intentFilter);
}
private class TestReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Toast.makeText(MainActivity.this, "action:" + action, Toast.LENGTH_SHORT).show();
}
}
protected void onDestroy() {
super.onDestroy();
//解绑
lm.unregisterReceiver(testReceiver);
}
使用的方式和BrocastReceiver也差不多,但是要注意的就是,我们用过LocalBroadcastManager.getInstance获取实例后,注册,解绑和发送都需要这个实例才可以
源码
我们来看下LocalBroadcastManager的源码是如何工作的,其实他的源码也没有多少,他获取是通过单例来实现的
public static LocalBroadcastManager getInstance( Context context) {
Object var1 = mLock;
synchronized(mLock) {
if (mInstance == null) {
mInstance = new LocalBroadcastManager(context.getApplicationContext());
}
return mInstance;
}
}
private LocalBroadcastManager(Context context) {
this.mAppContext = context;
this.mHandler = new Handler(context.getMainLooper()) {
public void handleMessage(Message msg) {
switch(msg.what) {
case 1:
LocalBroadcastManager.this.executePendingBroadcasts();
break;
default:
super.handleMessage(msg);
}
}
};
}
单例后,在构造函数里初始化了一个Handler,这个Handler我们等下将,接着我们先来看下他的注册:
public void registerReceiver( BroadcastReceiver receiver, IntentFilter filter) {
HashMap var3 = this.mReceivers;
synchronized(this.mReceivers) {
//构建广播消息体
LocalBroadcastManager.ReceiverRecord entry = new LocalBroadcastManager.ReceiverRecord(filter, receiver);
ArrayList<LocalBroadcastManager.ReceiverRecord> filters = (ArrayList)this.mReceivers.get(receiver);
if (filters == null) {
filters = new ArrayList(1);
//添加接收者
this.mReceivers.put(receiver, filters);
}
filters.add(entry);
for(int i = 0; i < filter.countActions(); ++i) {
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);
}
entries.add(entry);
}
}
}
注册的时候,他先构建了一个广播信息体ReceiverRecord,并且将我们注册传入的信息添加到Receiver,然后遍历Action,并且关联Action和事件,然后调用sendBroadcast去发送广播,他对数据做了处理之后,开始分类,也就有了我们的Bundler,Data之类的数据了,其实最后调用的代码:
this.mPendingBroadcasts.add(new LocalBroadcastManager.BroadcastRecord(intent, receivers));
if (!this.mHandler.hasMessages(1)) {
this.mHandler.sendEmptyMessage(1);
}
就是这一段,这一段也很简单,将广播加入mPendingBroadcasts后发送一个What为1的Handler,而这个Handler就是之前获取单例后他在构造方法里创建的,所以你看这个what=1的判断里,他最终执行的函数为executePendingBroadcasts,代码不多,可以贴出来:
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);
this.mPendingBroadcasts.clear();
}
for(int i = 0; i < brs.length; ++i) {
LocalBroadcastManager.BroadcastRecord br = brs[i];
int nbr = br.receivers.size();
for(int j = 0; j < nbr; ++j) {
LocalBroadcastManager.ReceiverRecord rec = (LocalBroadcastManager.ReceiverRecord)br.receivers.get(j);
if (!rec.dead) {
rec.receiver.onReceive(this.mAppContext, br.intent);
}
}
}
}
}
我们可以通过这个双层for循环看到他最终是取得了监听的广播消息体brs里的数据,得到一个BroadcastRecord,然后调用br.receivers.get获取到接收对象rec,再通过rec.receiver.onReceive通知监听着,实现了消息的发送和接收
整个设计理念就是观察者模式了,对象一对多的关系依赖,当一个对象发生改变的时候,他的所有依赖者都将受到通知并且自动更新。
开车完毕,Over!!!