BroadcastReceiver 广播机制
问题
Android 广播机制是什么?静态注册和动态注册有什么区别?
答案
1. 广播类型
| 类型 | 描述 | 接收顺序 |
|---|---|---|
| 标准广播 | 异步发送,几乎同时到达所有接收者 | 无序 |
| 有序广播 | 按优先级逐个传递,可拦截 | 按 priority |
| 本地广播 | 仅应用内传播(已废弃) | — |
| 粘性广播 | 发送后保留,新注册者可收到(已废弃) | — |
2. 动态注册(推荐)
class MyActivity : AppCompatActivity() {
private val networkReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val isConnected = intent.getBooleanExtra(
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false
)
updateNetworkStatus(!isConnected)
}
}
override fun onStart() {
super.onStart()
val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
// Android 14+ 需要指定 RECEIVER_NOT_EXPORTED
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerReceiver(networkReceiver, filter, RECEIVER_NOT_EXPORTED)
} else {
registerReceiver(networkReceiver, filter)
}
}
override fun onStop() {
super.onStop()
unregisterReceiver(networkReceiver) // ⚠️ 必须注销,否则内存泄漏
}
}
3. 静态注册
<!-- AndroidManifest.xml -->
<receiver
android:name=".BootReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
// 开机后启动 WorkManager 任务
WorkManager.getInstance(context).enqueue(syncWork)
}
}
}
Android 8.0+ 静态广播限制
从 Android 8.0 开始,大部分隐式广播不能通过静态注册接收。仍可静态注册的:
BOOT_COMPLETED(开机广播)LOCALE_CHANGED(语言切换)MY_PACKAGE_REPLACED(应用更新)- 自定义显式广播
其他广播必须使用动态注册。
4. 发送广播
// 标准广播
val intent = Intent("com.example.MY_ACTION").apply {
putExtra("data", "hello")
setPackage(packageName) // Android 8.0+ 显式指定包名
}
sendBroadcast(intent)
// 有序广播
sendOrderedBroadcast(intent, null)
// 应用内通信 —— 推荐替代方案
// LiveData / StateFlow / EventBus 而非 LocalBroadcastManager(已废弃)
5. 现代替代方案
| 场景 | 传统方案 | 现代方案 |
|---|---|---|
| 应用内事件通信 | LocalBroadcastManager | SharedFlow / EventBus |
| 系统事件监听 | BroadcastReceiver | 仍使用 BroadcastReceiver |
| 数据变化通知 | BroadcastReceiver | LiveData / StateFlow |
| 后台事件触发 | 静态 BroadcastReceiver | WorkManager |
常见面试问题
Q1: 动态注册和静态注册的区别?
答案:
| 特性 | 动态注册 | 静态注册 |
|---|---|---|
| 注册方式 | 代码中 registerReceiver | AndroidManifest.xml |
| 生命周期 | 随注册组件(需手动注销) | 随应用安装 |
| 接收时机 | 注册后到注销前 | 应用安装后始终可接收 |
| Android 8.0+ | 不受限 | 大部分隐式广播被限制 |
| 优先级 | 相同 action 时动态 > 静态 | — |
Q2: onReceive 中能执行耗时操作吗?
答案:
不能。onReceive 运行在主线程,且有 10 秒超时限制(有序广播),超时会 ANR。
override fun onReceive(context: Context, intent: Intent) {
// ❌ 不能做耗时操作
// ✅ 启动 WorkManager 或前台 Service 处理
val work = OneTimeWorkRequestBuilder<SyncWorker>().build()
WorkManager.getInstance(context).enqueue(work)
}
同时 onReceive 执行完后 BroadcastReceiver 实例就会被销毁,不能在其中启动异步任务(如线程、协程),因为进程可能被系统回收。