前言
上篇文章复习总结了Service的相关知识,现在开始复习BroadcastReceiver。BroadcastReceiver能够接受系统或者其他App发来的特定广播,本文先从广播的发送开始
一、发送广播的两种方式
1. sendOrderdBroadcast(Intent, String)
发送有序广播,优先级(通过android:priority或者setPriority设置)高的BroadcastReceiver会被优先收到(如果优先级相同,则动态注册的优先级高于静态注册的),其可以改变广播传递的内容或者直接中止该广播(通过调用abortBroadcast)
2. sendBroadcast(Intent, String)
发送无序广播,忽略广播接受者的优先级(因此无法被中止),所有广播接受者按照一种不确定的顺序接收到
二、BroadcastReceiver的两种注册方式
1. 静态注册
只需要新建一个类继承BroadcastReceiver,然后在清单文件application节点下,配置receiver节点即可,例如下面这段代码就配置了一个可用于接受飞行模式开关状态的BroadcastReceiver
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE" />
</intent-filter>
</receiver>
静态注册的BroadcastReceiver只要应用程序进程没被杀死就能接受到对应的广播,但是其没法接受某些系统的广播例如屏幕打开关闭、电量改变等
2. 动态注册
动态注册首先需要创建一个派生于BroadcastReceiver的实例,然后再创建一个IntentFilter实例设置该BroadcastReceiver关注哪几种广播,最后调用registerReceiver注册广播,例如以下代码就动态注册了一个BroadcastReceiver
val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION).apply {
addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED)
}
registerReceiver(br, filter)
动态注册可以接受到静态注册无法接收到广播例如屏幕打开关闭、电量改变等,此外动态注册的广播我们在用完以后应该调用unregisterReceiver解除注册,虽然系统也会帮我们解除,但是会打印错误
三、使用BroadcastReceiver的注意点
虽然系统规定BroadcastReceiver的onReceive最多执行10秒,但是由于该方法运行于主线程所以其实超过5秒就会ANR,如果我们要在onReceiver执行耗时任务里面就会想到开一个线程执行,但是当onReceive调用完毕后系统就会去销毁该实例,这样那个新建的线程优先级就非常低了很容易被杀死,导致达不到我们要效果。有以下两种方法可以用于解决这种情况。
- 通过在
onReceive中调用goAsync获得PendingResult对象以后再开启子线程,在执行结束时调用PendingResult.finish。 - 通过在
onReceive中启动服务(比如IntentService)运行耗时任务
四、本地广播和粘性广播
这两种广播都可以使用开源库EventBus代替