BroadcastReceiver是Android四大组件之一,重要性不言而喻。本文从BroadcastReceiver的简介、分类及使用场景、注册方式、广播的实现原理、本地广播的原理五个点来总结归纳一下BroadcastReceiver相关知识点,并在文后罗列一些常见的面试题作为思考和回顾。
一、BroadcastReceiver简介
1. Broadcast(广播):一种广泛应用在应用程序之间传输信息的机制。
2. BroadcastReceiver(广播接收器):用于接收来自系统和其他应用的广播,并对其进行响应的组件。
- 广播接收器是一个系统全局的监听器,用于监听系统全局的Broadcast消息,所以它可以很方便地进行系统组件之间的通信。
- 它拥有自己的进程,只要存在与之匹配的Broadcast被以Intent的形式发送出来,BroadcastReceiver就会被激活。
- 与其他四大组件一样,BroadcastReceiver也有自己独立的生命周期,但是它又和Activity、Service不同。
- 当在系统注册一个BroadcastReceiver之后,每次系统以一个Intent的形式发布Broadcast的时候,系统都会创建与之对应的BroadcastReceiver广播接收者实例,并自动触发它的onReceive()方法,当onReceive()方法被执行完成之后,BroadcastReceiver的实例就会被销毁。
二、BroadcastReceiver的分类
1. 标准广播(Normal broadcast)
- 是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。
2. 有序广播(Ordered broadcast)
- 则是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递。所以此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以先收到广播消息,并且前面的广播接收器还可以截断正在传递的广播,这样后面的广播接收器就无法收到广播消息了。
3. 本地广播(Local Broadcast)
可理解为一种局部广播,广播的发送者和接收者都同属于一个App。相比于全局广播(普通广播),App应用内广播优势体现在:安全性高 & 效率高。
三、BroadcastReceiver的两种注册方式
静态注册:广播接收器的生命周期是否系统决定的,当广播到达时,由系统实例化广播接收器,并执行onReceive()方法,当onReceive()执行完成后,当前广播接收器所在进程会变成空进程,容易被系统回收。故不管应用有没有开启,均可以收到其他应用或系统发送的广播。
动态注册:广播接收器的生命周期由当前注册广播接收器位置所在的组件决定(Activity,Service等),当应用退出时,广播接收者会被取消注册,无法接受到广播。
备注:Android 8.0新特性-取消大部分静态注册广播。8.0以后,静态注册的广播接受者是可以接收到广播的,只要广播是通过显示方式发送的。
解决方法:
1. 使用动态广播代替静态广播。
2. 保留原来的静态广播,但是加入组件参数。
3. 发送广播的时候携带intent.addFlags(0x01000000); 即能让广播突破隐式广播限制。
四、广播实现原理
Android 中的广播使用了设计模式中的观察者模式:基于消息的发布/订阅事件模型。模型中有3个角色:1. 消息订阅者(广播接收者) 2. 消息发布者(广播发布者) 3. 消息中心(AMS,即 Activity Manager Service)。
原理描述:
1. 广播接收者 通过 Binder 机制在 AMS 注册。
2. 广播发送者 通过 Binder 机制向 AMS 发送广播。
3. AMS 根据 广播发送者 要求,在已注册列表中,寻找合适的广播接收者寻找依据:IntentFilter / Permission。
4. AMS 将广播发送到合适的广播接收者相应的消息循环队列中;
5. 广播接收者通过消息循环拿到此广播,并回调 onReceive()特别注意:广播发送者和广播接收者的执行是异步的,发出去的广播不会关心有无接收者接收,也不确定接收者到底是何时才能接收到。
LocalBroadcastManager是Android系统提供的一个广播管理器,它可以通过Handler实现高效的广播发送。它的sendBroadcast()方法实际上是通过handler发送一个Message实现的。相比于系统广播通过Binder实现,LocalBroadcastManager使用Handler来实现广播发送,因此更高效。此外,LocalBroadcastManager内部协作主要是靠着两个Map集合:mReceivers和mActions,当然还有一个List集合mPendingBroadcasts,这个主要就是存储待接收的广播对象。
常见面试题包括:两种注册广播方式的区别、全局广播和本地广播的区别、广播的实现原理等。