05_Broadcast源码机制与面试要点_修订版
05 Broadcast 源码机制与面试要点
基于原 PDF 修订、联网校对并补充缺失内容
1. 系统广播的大致链路
从源码角度看,系统广播不是“直接调用所有 receiver”。发送、注册、查询匹配、排队和进程调度都经过系统服务协调。面试时可以用下面的链路表达,不需要死背每个类名。
- 接收方注册:Manifest receiver 由 PackageManager 解析安装包得到;动态 receiver 通过 registerReceiver 走 Binder 注册到系统服务。
- 发送方发送:sendBroadcast/sendOrderedBroadcast 通过 Binder 把 Intent 交给 ActivityManagerService/ActivityManager 相关服务。
- 系统匹配:根据 action、data、category、package、component、permission、用户等条件匹配 receiver。
- 广播入队:普通广播可并行/异步调度;有序广播按顺序串行推进。
- 进程处理:如果目标进程不存在且允许唤起,系统启动应用进程;最终通过主线程 Handler 调用 BroadcastReceiver.onReceive。
- 生命周期结束:onReceive 返回后,receiver 对象就不再活跃;如果进程没有其他重要组件,系统可以回收进程。
2. 修正原 PDF 的源码表述
| 原 PDF 表述 | 问题 | 修正说法 |
|---|---|---|
| 自定义 BroadcastReceiver,并且重写 onReceiver() | 方法名错误。 | 应为重写 onReceive(Context, Intent)。 |
| AMS 将广播发送到相应 BroadcastReceiver(一般情况下是 Activity)的消息队列中 | BroadcastReceiver 不是 Activity;“一般情况下是 Activity”不准确。 | 系统把消息分发到目标应用进程的主线程/ReceiverDispatcher,再回调 receiver.onReceive。 |
| 本地广播只在 app 内传播 | 对 LocalBroadcastManager 来说更准确是同一进程内的应用级事件总线。 | 它已废弃;仅作为历史实现理解。 |
| 静态注册一定能在程序未启动时收到广播 | 忽略 Android 8.0 后隐式广播限制。 | manifest receiver 是入口之一,但是否能唤起取决于广播类型、targetSdkVersion、权限、显式/隐式等。 |
3. 普通广播、有序广播、粘性广播的机制差异
| 类型 | 调度特点 | 结果传递 | 是否推荐 |
|---|---|---|---|
| 普通广播 | 匹配后分发给接收者,不提供可依赖顺序 | 无 | 系统事件和简单通知可用,但内部事件可考虑 Flow/LiveData。 |
| 有序广播 | 按优先级/顺序逐个分发 | 可 setResult/abort | 仅在确实需要顺序和结果传递时使用。 |
| Sticky Broadcast | 广播结束后缓存 Intent,后注册 receiver 可能收到历史值 | 可被重放/篡改风险 | 不推荐,避免新业务使用。 |
4. LocalBroadcastManager 历史实现
LocalBroadcastManager 曾经常被用于应用内事件分发。它不经过系统 AMS,不走跨进程 Binder 广播路径,而是在应用进程内维护 receiver/action 映射,并通过 Handler 把待分发事件投递回主线程。
- mReceivers:记录 receiver 对应的过滤器。
- mActions:记录 action 到 receiver 的映射。
- mPendingBroadcasts:记录待投递广播。
- 优点是进程内开销低;缺点是架构上像全局事件总线,类型不安全,已经废弃。
5. 面试题速记
| 问题 | 回答要点 |
|---|---|
| Broadcast 有哪些注册方式? | Manifest-declared 和 Context-registered;前者可作为系统入口但受版本限制,后者与 context 生命周期绑定。 |
| 有序广播和普通广播区别? | 有序广播串行、可传递结果和中断;普通广播不保证顺序,不适合依赖结果链。 |
| 为什么 onReceive 不能做耗时任务? | 通常在主线程执行,receiver 活跃期短,超时可能 ANR;返回后进程可能被回收。 |
| Android 8.0 对广播有什么限制? | target 26+ 不能在 manifest 中注册大多数隐式广播,除豁免项或显式发给应用。 |
| Android 14 动态 receiver 要注意什么? | target 34+ 一般要指定 RECEIVER_EXPORTED 或 RECEIVER_NOT_EXPORTED。 |
| LocalBroadcastManager 还能用吗? | 历史项目可能见到,但已废弃;新代码用 LiveData/Flow/Reactive streams 等观察者方案。 |
6. 一句话总结
Broadcast 是系统级低耦合通知机制,不是通用事件总线,也不是后台保活工具。现代 Android 开发中,使用 Broadcast 要优先考虑生命周期、后台限制和安全边界。
参考资料
- Android Developers - Broadcasts overview: https://developer.android.com/develop/background-work/background-tasks/broadcasts
- Android Developers - Implicit broadcast exceptions: https://developer.android.com/develop/background-work/background-tasks/broadcasts/broadcast-exceptions
- Android Developers - BroadcastReceiver API reference: https://developer.android.com/reference/android/content/BroadcastReceiver
- Android Developers - LocalBroadcastManager release notes: https://developer.android.com/jetpack/androidx/releases/localbroadcastmanager
- Android Developers - Android 14 behavior changes: https://developer.android.com/about/versions/14/behavior-changes-14
- Android Developers - Android 12 behavior changes: https://developer.android.com/about/versions/12/behavior-changes-12
- Android Developers - ConnectivityManager API reference: https://developer.android.com/reference/android/net/ConnectivityManager
- Android Developers - Sticky broadcasts risk: https://developer.android.com/privacy-and-security/risks/sticky-broadcast