本节书摘来自异步社区《Android开发进阶:从小工到专家》一书中的第1章,第1.3节Broadcast(广播),作者 何红辉,更多章节内容可以访问云栖社区“异步社区”公众号查看
1.3 Broadcast(广播)Broadcast是一种广泛运用的、在应用程序之间传输信息的机制,Android中的广播与传统意义上的电台广播类似,一个广播可以有任意个接收者。广播机制是一个典型的发布—订阅模式,也就是我们所说的观察者模式。广播机制最大的特点就是发送方并不关心接收方是否接到数据,也不关心接收方是如何处理数据的,通过这样的形式来达到接、收双方的完全解耦合。
Android广播机制包含 3 个基本要素,分别是用于发送广播的Broadcast、接收广播的BroadcastReceiver以及用于传递信息的Intent。Android广播可分为普通广播、有序广播、本地广播和Sticky广播。
1.3.1 普通广播普通广播是完全异步的,通过Context的sendBroadcast()函数来发送,消息传递的效率比较高,但所有的receivers(接收器)的执行顺序不确定。缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播,直到没有与之匹配的广播接收器为止。
首先我们需要定义一个广播接收器,示例如下:
public class HelloBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "hello", Toast.LENGTH_LONG).show(); } }第二步是注册广播,形式与Activity、Service的注册类似,可以通过AndroidManifest.xml或者代码进行注册,分别是静态注册和动态注册。xml注册示例如下:
<receiver android:name=".broadcast.HelloBroadcastReceiver" > <intent-filter> <action android:name="hello"/> </intent-filter> </receiver> 动态注册的示例代码为: private void registerHelloBroadcast() { registerReceiver(new HelloBroadcastReceiver(), new IntentFilter(HELLO_ACTON)) ; } 如果是在Activity或者Fragment中动态测试,那么不要忘了在执行onDestory时注销该广播。注册之后就可以发送广播了,代码如下所示: private void sendNormalBroadcast() { sendBroadcast(new Intent(HELLO_ACTON)); }然后就会调用HelloBroadcastReceiver的onReceive函数,在该函数中执行相关操作即可。
1.3.2 有序广播有序广播通过Context.sendOrderedBroadcast()来发送,所有的广播接收器按照优先级依次执行,广播接收器的优先级通过receiver的intent-filter中的android:priority属性来设置,数值越大优先级越高。当广播接收器接收到广播后,可以使用setResult()函数来结果传给下一个广播接收器接,然后通过getResult()函数来取得上个广播接收器接返回的结果,并可以用abortBroadcast()函数来让系统丢弃该广播,使该广播不再传送到别的广播接收器接。
设置广播的优先级示例:
<receiver android:name=".broadcast.HelloBroadcastReceiver" > <intent-filter android:priority="100"> <action android:name="hello"/> </intent-filter> </receiver> 发送有序广播: private void sendOrderBroadcast() { sendOrderedBroadcast(new Intent(HELLO_ACTON), null); }1.3.3 本地广播在21版的Support v4包中新增本地广播,也就是LocalBroadcastManager。之前广播都是全局的,所有应用程序都可以接收到,这样就会带来安全隐患。但是,有的时候我们并不需要把自己应用内的信息广播给所有应用,而只是进程内使用,现在使用Support v4包中的LocalBroadcastManager就能够实现限于应用内的广播。
它的用法很简单,只需要把调用context的sendBroadcast、registerReceiver 、unregisterReceiver 的地方替换为LocalBroadcastManager getInstance (Context context)中对应的函数即可,如图1-1所示。
本地广播与普通广播只是操作的类不一样,其他的接口基本上都类似,因此,替换为本地广播的成本相对较低。为了程序的安全性,建议在不需要其他进程接收广播的情况下使用本地广播。
1.3.4 sticky广播sticky广播通过Context.sendStickyBroadcast()函数来发送,用此函数发送的广播会一直滞留,当有匹配此广播的广播接收器被注册后,该广播接收器就会收到此条广播。使用此函数发送广播时,需要获得BROADCAST_STICKY权限:
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>sendStickyBroadcast只保留最后一条广播,并且一直保留下去,这样即使已经有广播接收器处理了该广播,当再有匹配的广播接收器被注册时,此广播仍会被接收。如果你只想处理一遍该广播,可以通过removeStickyBroadcast()函数实现。