静态广播接收者、动态广播接收者对比
知识点提取出的demo:
用两种方式实现如下需求(使用动态和静态注册广播):编写一个程序,要求在activity中点击一个button,发送一个广播(该广播的intent中携带一个字符串数据),自定义一个广播接受者,接收到这个广播之后toast显示activity发送过来的内容。
相关知识点:
广播接收器可以自由地对自己感兴趣的广播进行注册,这样当有相应的广播发出(demo中button按钮)时,广播接收器就能够收到该广播(demo中的接收广播),并在内部处理相应的逻辑(toast显示activity发送过来的内容).注册广播的方法一般有如下两种:
静态注册:在AndroidManifest.xml中注册广播。AndroidManifest中声明<receiver>,需要在其中配置<intentfilter>指定接收广播的动作(action)。主要用于一般性的广播。
动态注册:在Java代码中注册。一般用于发送频次高的广播,比如接收手机每时每刻的电量、屏幕的开启与关闭。
两种注册的区别:代码注册,它不是常驻型广播,也就是说广播跟随程序的生命周期,一旦代码所在进程被杀死,广播接收者就失效。清单文件注册是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。一旦应用程序被部署到手机,广播接收者就会生效,高版本的模拟器(3.2以上)中的接收者,需要启动过一次才能接收到广播。
动态注册的广播接收器可以自由地控制注册与注销,在灵活方面有很大的优势,但是也存在一个明显的缺点:必须程序开启后才能接收到广播,因为注册的逻辑实在onCreate方法中写的.比如我们需要让程序接收一条开机的广播,就需要使用静态注册了.
demo代码实现:
(1) 注册动态广播:
在动态广播中,首先我们创建IntentFilter的实例,并给它添加了一个值为"csdn.net.test202"的action.为什么要添加这个值呢?因为我们在点击button1时,会发出一条值为csdn.net.test202的广播(说白了,这是我们自定义的.如果是系统广播,这里的action就对应系统发送的action值.类似于一个暗号,发送暗号和接收暗号对应了,才能接收).我们的广播接收器想要监听什么广播,就要添加对应的action值.
注意,动态注册的广播接收器一定要取消注册才行.
静态广播的注册,通过android studio(as)开发工具,其实非常智能、人性化,只需要按照下图操作即可.不仅帮你生成了继承BroadcastReceiver的相关代码,AndroidManifest中的代码也生成了.但as还没智能到知道你的action值是什么.所以还需要在AndroidManifest的<internt-filter>标签里添加相应的action.
(2)发送广播:
(3)接收广播:
补充说明:
1.上述的demo例子,其实是广播中的自定义广播,action值由自己进行定义.只需要保持发送方、接收方的action一直即可(当然最好见名之意).另外,还有一种比较常见的,就是接收系统广播,比如接收手机电量的变化、网络变化,因为广播的发送方是系统.对于这种情况,就需要使用到系统广播了.而系统广播的action值不需要记,估计你也记不住.使用到的时候,很容易搜索到.
2(面试很容易问到).上述demo中的广播接收器的onReceiver()方法中我们是通过toast进行进行演示的.在实际的项目中,往往是需要进行逻辑的处理.需要注意的是:不要在onReceiver()方法中添加过多的逻辑或者任何的耗时操作.广播接收器中是不允许开启线程的,因为BroadcastReceiver的生命周期很短(在onReceive()执行后BroadcastReceiver的实例就会被销毁),子线程可能还没有结束BroadcastReceiver就先结束了.如果BroadcastReceiver结束了,它的宿主进程还在运行,那么子线程还会继续执行。但宿主进程此时很容易在系统需要内在时被优先杀死.从而抛出ANR异常(ANR:Application Not Responding.应用程序无响应).
因此,广播更多的时候扮演一种打开程序其他组件的角色,比如创建一条状态栏通知,或者开启一个服务.
3.在2中,如果我们需要进行耗时操作的话,应该通过发送Internt给Service(服务),交由它去处理.
4.广播机制简介:
广播主要分为标准广播和有序广播.其中:
标准广播(Normal Broadcasts)是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时间接收到这条广播,就好比中学时代,学校播音室进行听力训练,播音室发出广播后,各个班级都可以几乎同时接收到.标准广播是没有任何先后顺序可言的,它的效率会比较高,但同时意味着它是无法被截断的.
有序广播(Ordered Broadcasts)则是一种同步的广播,在广播发出后,同一时刻只会有一个广播接收器能够接收到这条消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递.就好比国家的一份重要文件,先由中央传到各省(直辖市),省(直辖市)只有执行完毕后,再传递到各市.有序广播的广播接收器是有先后顺序的,优先级高的可以先接收到广播,并且前面的广播接收器还可以拦截正在传递的广播,这样后面的广播接收器就无法收到消息了.
(标准广播工作示意图)
(有序广播工作示意图)
5.本地广播:
上面我们发送和接收的广播全部属于系统全局广播,即发出的广播可以被其他任何应用程序接收到,并且我们还可以接收来自其他任何应用程序的广播.这样就很容易引起安全性的问题.比如我们发送的一些携带关键性数据的广播有可能被欺压的应用程序截获,或者其他的程序不停地向我们的广播接收器里发送各种垃圾广播.
为了能够解决广播的安全性问题,android引入了一套本地广播体系,使用这个机制发出的广播只能够在应用程序的内部进行传递,并且广播接收器也只能接收来自本应用程序发出的广播,这样所有的安全问题就不存在了.
本地广播的用法并不复杂,主要是使用一个LocalBroadcastManger来对广播进行管理,并提供了发送广播和注册广播接收器的方法.基本使用见源码LocalBroadcastActivity类.查看源码后你会发现,它的使用和动态注册广播接收器以及发送广播的代码时一样的.
另外,需要说明的是:本地广播是无法通过静态注册的方式来接收的.同时,相比系统全局广播,本地广播除了安全的优势外,还比发送系统全局广播更加高效.