Android四大组件之BroadcastReceiver篇

411 阅读2分钟

前言

上篇文章复习总结了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调用完毕后系统就会去销毁该实例,这样那个新建的线程优先级就非常低了很容易被杀死,导致达不到我们要效果。有以下两种方法可以用于解决这种情况。

  1. 通过在onReceive中调用goAsync获得PendingResult对象以后再开启子线程,在执行结束时调用PendingResult.finish。
  2. 通过在onReceive中启动服务(比如IntentService)运行耗时任务

四、本地广播和粘性广播

这两种广播都可以使用开源库EventBus代替