什么是广播
在Android中,广播是一种广泛运用的在应用程序之间传输信息的机制,Android中我们要发送的广播内容是一个Intent,这个Intent中可以携带我们要传送的数据。比如我们可以使用广播来实现Activity与Service之间的通信,而不必使用bindService;还有一个常用的场景就是当我们在应用中退出登录后,需要调到登录界面,而之前的主界面可以发送一个广播来通知主界面销毁自己。
广播的种类
广播一共有以下3种类型:
- Normal Broadcast:普通广播,调用方法是Context.sendBroadcast
- System Broadcast:系统广播(开机、电量低),调用方法是Context.sendOrderedBroadcast
- Local Broadcast:本地广播,只在自身APP内传播,内部实现机制是Handler
广播的使用场景
- 同一个App具有多个进程的不同组件之间的消息通信,定位服务一般都会在一个单独的进程中,通过广播告诉其他进程定位信息
- 不同app之间的组件之间的消息通信,比如系统电话
实现广播
实现广播有两种方式:
- 静态注册:
在AndroidManifest.xml里通过<receiver>标签声明
<receiver
android:enabled=["true" | "false"]
//此broadcastReceiver能否接收其他App的发出的广播
//默认值是由receiver中有无intent-filter决定的:如果有intent-filter,默认值为true,否则为false
android:exported=["true" | "false"]
android:icon="drawable resource"
android:label="string resource"
//继承BroadcastReceiver子类的类名
android:name=".mBroadcastReceiver"
//具有相应权限的广播发送者发送的广播才能被此BroadcastReceiver所接收;
android:permission="string"
//BroadcastReceiver运行所处的进程
//默认为app的进程,可以指定独立的进程
//注:Android四大基本组件都可以通过此属性指定自己的独立进程
android:process="string" >
//用于指定此广播接收器将接收的广播类型
//本示例中给出的是用于接收网络状态改变时发出的广播
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
创建一个类继承自BroadcastReciver,然后复写其中的onReceive()方法,判断相应的action即可。
静态注册的广播会一直存在,不管app是否是运行的,只要接收到注册的广播就会执行onRecive里的代码。
- 动态注册:
需要在activity中动态的registerReceiver
// 选择在Activity生命周期方法中的onResume()中注册
@Override
protected void onResume(){
super.onResume();
// 1. 实例化BroadcastReceiver子类 & IntentFilter
mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
// 2. 设置接收广播的类型
intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);
// 3. 动态注册:调用Context的registerReceiver()方法
registerReceiver(mBroadcastReceiver, intentFilter);
}
// 注册广播后,要在相应位置记得销毁广播
// 即在onPause() 中unregisterReceiver(mBroadcastReceiver)
// 当此Activity实例化时,会动态将MyBroadcastReceiver注册到系统中
// 当此Activity销毁时,动态注册的MyBroadcastReceiver将不再接收到相应的广播。
@Override
protected void onPause() {
super.onPause();
//销毁在onResume()方法中的广播
unregisterReceiver(mBroadcastReceiver);
}
}
相比于静态注册,动态注册的广播跟随着activity的生命周期,同时为了防止内存溢出,需要在activity的onDestory方法中调用unregisterReceiver(mBroadcastReceiver);
广播的内部实现机制
- 自定义广播接收者BroadcastReceiver,并复写onReceive()方法
- 通过Binder机制向AMS(Activity Manager Service)进行注册
- 广播发送者通过Binder机制向AMS发送广播
- AMS查找符合相应条件的BroadcastReceiver,将广播发送到BroadcastReceiver相应的消息循环队列中
- 消息循环执行拿到此广播,回调BroadcastReceiver中的onReceiver方法
本地广播的优点
- 使用它发送的广播将只在自身app内传播,因此你不必担心泄漏隐私数据
- 其他App无法对你的app发送广播,因为你的app根本就不可能接收到非自身应用发送的该广播,因此不必担心有安全漏洞可以利用
- 它比系统广播更加高效
LocalBroadcastManager源码分析
首先我们看源码要有目的的去看,而且入口点是你调用的方法,从该方法去看
这里的入口就是registerReceiver
public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
synchronized (mReceivers) {
//保存的是filter和receiver
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);
}
}
}
再来看发送广播的方法,这里只截取的关键的一部分
if (receivers != null) {
for (int i=0; i<receivers.size(); i++) {
receivers.get(i).broadcasting = false;
}
mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));
if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {
mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);
}
return true;
}
可以看到它内部是使用Handler来发送的,这就说明了它比系统广播更加的高效。
网友评论