广播

广播

十一月 09, 2017

1. 广播

1.1 广播定义

(类似观察者模式)
在Android中,Broadcast是一种广泛运用的在应用程序之间的传输信息的机制, Android中我们要发送的广播内容是一个Intent,这个Itent中可以携带我们要传送的数据。

*1. 广播实现的不同程序间的数据传输与共享(只要和发送广播的Action相同的接收者都可以接收到)
*2. 广播接收者通知作用(在程序中通过广播接收者来更新UI,避免了Service与Activity进行交互)

1.2 广播场景

A. 同一App内具有多个进程的不同组件之间的消息通信
B. 不同App间的组件之间消息通信(推广运营)

1.3 广播种类

  1. Nromal Broadcast : Context.sendBroadcast(普通广播)
  2. System Broadcast: Context.sendOrderedBroadcast(有序广播\系统广播)
  3. Local Broadcast: 只在自身App内传播(本地广播)

2. 实现广播-receiver(接收Broadcast)

1.静态注册: 注册完成就一直运行(Manifest文件中,Activity销毁仍能接收广播,缺点:不灵活)
2. 动态注册,跟随Activity的生命周期(onDestroy中要销毁,跟随Activity)

区别: 动态在代码中调用 registerReceiver
静态在Manifest里写入

| 实现方式/区别 | 声明| 生命周期|
|—|—|—|—|—|—|
| 动态注册| registerReceiver| 跟随Activity|
| 静态注册| Manifest| 被销毁了仍能运行接收|

3. 广播实现机制

3.1 自定义广播接收者BroadcastReceiver,并复写onReceive()方法;

3.2. 通过Binder机制想*AMS(Activity Manager Service) 进行注册;

3.3 广播发送这通过Binder机制向AMS发送广播;

3.4 AMS查找符合相应条件(IntentFilter/Permission等) 的BroadcastReceiver, 将广播发送到BroadcastReceiver(一般情况下是Activity) 相应的消息循环队列中;

3.5 消息循环执行拿到此广播, 回调BroadcastReceiver中的onReceive()方法;

*AMS:AMS是作为管理Android系统组件的核心服务,他在SystemServer执行run()方法的时候被创建,并运行在独立的进程中。具体来说就是SystemServer管理着Android中所有的系统服务,这些系统服务的生命周期回调都由SystemServer去调度负责。

4. LoacalBroadcastManager详解

4.1 使用它发送的广播将只在自身内传播, 不必担心泄露隐私数据;

4.2 其他App无法对你的App发送该广播

因为你的App根本不可能收到其他非自身应用发送的广播, 避免了安全漏洞的利用;(防止其他人获取到action 并篡改, 如植入广告等)

4.3 比系统全局广播更高效;

在LocalBroadcastReceiver中三个集合类:

4.3.1 mReceivers:

是一个HashMap,key是receiver , value是intentfilter

1
private final HashMap<BroadcastReceiver, ArrayList<IntentFilter>> mReceivers

4.3.2 mActions:

key是Action, value 是arrylist ,是对应的receiverRecord

1
private final HashMap<String, ArrayList<ReceiverRecord>> mActions

4.3.3 mPendingBroadcasts:

存储BroadcastRecord对象的(intent和receivers) 作用:存储和发送广播的action匹配的ReceiverRecord的集合,在执行时会遍历的集合里面广播接收器(存储了广播接收器的存储器)

1
2
private final ArrayList<BroadcastRecord> mPendingBroadcasts
= new ArrayList<BroadcastRecord>();

4.3.4 注册方法:registerReceiver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* 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);
ArrayList<IntentFilter> filters = mReceivers.get(receiver);
if (filters == null) {
filters = new ArrayList<IntentFilter>(1);
mReceivers.put(receiver, filters);
}
filters.add(filter); //添加过滤规则
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);//将里面的Filter分别建立了Arraylist映射,通过广播接收器来接收
}
}
}

4.3.5 unregisterReceiver:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
* 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(BroadcastReceiver receiver) {
synchronized (mReceivers) {
ArrayList<IntentFilter> filters = mReceivers.remove(receiver);
if (filters == null) {
return;
}
for (int i=0; i<filters.size(); i++) {
IntentFilter filter = filters.get(i);
for (int j=0; j<filter.countActions(); j++) {
String action = filter.getAction(j);
ArrayList<ReceiverRecord> receivers = mActions.get(action);
if (receivers != null) {
for (int k=0; k<receivers.size(); k++) {
if (receivers.get(k).receiver == receiver) {
receivers.remove(k);//将myreceiver中的广播接收器删除
k--;
}
}
if (receivers.size() <= 0) {
mActions.remove(action);//把mActions中集合类删除
}
}
}
}
}
}

4.3.6 sendBroadcast:

1
2
3
4
5
6
7
8
9
10
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;
}

4.4 LocalBroadcastMananger 高效的原因

4.4.1 内部通过HandlersendBroadcast()方法

主要是它内部通过HandlersendBroadcast()方法含义并非平时所用,它的sendBroadcast()方法其实是通过handler发送一个Message实现的;

4.3.2 内部通过Handler来实现广播发送

既然是它内部通过Handler来实现广播发送的,那么相比系统广播通过Binder实现肯定高效,同事用Handler来实现,别的应用无法像我们的应用发送该广播,而我们的应用内发送的广播也不会离开我们的应用;

4.3.3 LocalBroadcastMananger 内部协作

主要是靠这两个集合:mReceivers和mActions, 还有一个List集合mPedingBroadcasts, 这个主要就是存储待接收的广播对象;