Android 四大组件—组件间的通信方式Broadcast(广播)
前言:假设有这样一个场景:在程序中要将一条消息同时发送给多个接收者,比如应用中启动的多个Activity,或者系统中的其他多个应用,但是并不必关心接收者是否接收到或者如何处理,该如何实现呢?想想现实中,当我们遇到类似的情况的时候,最好的方法是什么?相信大家很容易就能想到了。没错,就是广播。在Android中,同样也提供了广播机制来实现这种功能。
一、概念
Android中的广播与传统意义上的电台广播类似,具有单向、群发,且不关注结果的特点。就是说,一个广播发送者负责将广播发送给任意个广播接收者,并且发送者并不关心接收者是否接收到广播或如何处理。这是一种典型的发布—订阅模式,即观察者模式。通过这种模式,实现了发送方和接收方的完全解耦,增加了系统的集成和扩展性。
二、适用场景分析
Broadcast作为Android中组件间的通信方式,其主要适用的场景有:
(1)同一App内部同一组件内的消息通信(单个或多个线程)
(2)同一App内部不同组件间的消息通信(单个进程)
(3)同一App具有多个进程的不同组件间的消息通信
(4)不同App之间的组件间的消息通信
(5)特定情况下系统与App间的消息通信
以上列出的是Broadcast的适用场景,然而并非在每个场景下都要用Broadcast。下面来具体分析:
场景(1):由于该类问题可以通过诸如“扩展变量作用域”、“基于接口的回调”、“Handler—post/Handler—Message”等方式进行处理,因此不推荐使用Broadcast。
场景(2):对于某些比较复杂的情况,有时候基于接口的回调方式可能不太方便解决问题。此时,形如EventBus一类的事件发布/订阅框架将会是很好的解决方案。然而,有些人可能还没有接触过这类框架,那么使用Broadcast也是很好的选择。
场景(3)(4)(5):由于涉及到不同进程间的通信,适时的使用Broadcast应该是非常适宜的方案。
三、Broadcast的使用
Android中的广播分为普通广播、有序广播、本地广播、粘性广播、以及系统广播。下面分别来看一下。
3.1 广播的使用
由于几种类型的广播的使用方式大体上相同,只是在具体的发送方法上有所差异。因此先统一简述一下广播的使用步骤:
(1)广播的3个要素
Android中的广播机制包含3个基本要素,分别是用于发送广播的Broadcast,用于接收广播的BroadcastReceiver,以及用于传递信息的Intent。
(2)广播的发送
要发送一个广播,写法很简单,这里以发送普通广播为例,只需在需要发送广播的地方执行下列代码:
//实例化Intent对象 Intent intent = new Intent(); //设置action,这里的action与IntentFilter的action对应 intent.setAction("test"); //设置要传递的信息 intent.putExtra("broadcast", "test"); //发送广播 sendBroadcast(intent);
(3)广播的接收
广播的接收,需要弯沉两个步骤。首先需要先创建一个广播接收者BroadcastReceiver,然后还要注册对应的广播。
BroadcastReceiver的创建只需新建一个类,继承BroadcastReceiver类即可。创建好后,会覆写一个onReceive()方法,当接收到广播后,便会回调此方法。代码如下:
package com.test.myapplication; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class MyReceiver extends BroadcastReceiver { public MyReceiver() { } @Override public void onReceive(Context context, Intent intent) { //接收到广播后会回调此方法 } }
创建好BroadcastReceiver后,接下来还需要注册。注册的方式有两种:静态注册和动态注册。
● 静态注册:就是在AndroidManifest.xml里面注册广播。这种方式的特点是所注册的广播是基于整个应用的,即无论在app运行的任何时刻,只要系统中有对应的广播发出,且app具有接收权限,那么app都会接收到该广播。注册方式如下:
<receiver android:name=".MyReceiver" android:enabled="true" android:exported="true" android:permission="test" android:process="test"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver>
上面的代码在AndroidManifest.xml里面对新建的BroadcastReceiver进行了注册,其中设置了接收的广播类型为系统的短信消息:
name属性,就是新建的BroadcastReceiver的"包名.类名",
exported属性,其作用是决定此BroadcastReceiver能否接收其他App所发出的广播。其值由有无intent-filter来决定。当有intent-filter的时候,其值默认为true,如果没有则默认为false。当然也可以手动修改。
permission属性,当设置时,只有拥有对应权限的app所发送的广播才会被接收到,其他广播则不会被接收。
progress属性:设置BroadcastReceiver所在的进程,默认为App进程。
<intent-filter>:指定此BroadcastReceiver所接收的广播类型。其中的action与发送广播是所设置的setAction()方法的参数对应。
● 动态注册:动态注册就是在代码中通过registerReceiver()方法进行注册。只需在需要注册的地方执行下列代码:
//实例化IntentFilter对象 IntentFilter intentFilter = new IntentFilter(); //设置接收广播的类型。与发送广播时的setAction()方法对应 intentFilter.addAction("test"); //注册BroadcastReceiver registerReceiver(mReceiver, intentFilter);
然后在无需接收广播的时候,要记得使用unregisterReceiver()取消注册。例如在Activity关闭的时候,在onDestory()里面:
@Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(mReceiver); }
注意:Android中凡是涉及register的,必须在适当的时机进行unregister。
3.2 几种类型的广播介绍
(1)普通广播
普通广播通过Context.sendBroadcast()方法来发送,消息传递效率比较高,但所有接收方接收消息的顺序是无需的,即无法确定哪个接收方会先收到广播消息。普通广播一旦发送便无法终止,直到没有与之匹配的广播接收器为止。
另外,由于Android 4.2中加入了多用户特性,因此演变出了sendBroadcastAsUser()方法来区分不同的用户。
(2)有序广播
有序广播通过Context.sendOrderedBroadcast()方法来发送。有序广播具有以下特性:
● 所有的广播接收器会依照优先级依次接收广播消息。广播接收器的优先级通过intent-filter的priority属性来设置,数值越大优先级越高。如果优先级相同,则动态注册的接收器会先于静态注册的接收器先接收到广播。
● 当某个广播接收器接收到广播后,可以通过setResult()方法来修改广播的内容,然后在下个广播接收器中使用getResultData()、getResultExtras()方法来接收修改后的结果,或者使用intent.getXXX()方法来接收广播的原始消息。在广播传播的过程中,还可以使用abortBroadcast()方法来终止广播的发送,使广播不再继续向下传播。
(3)粘性广播
粘性广播通过Context.sendStickyBroadcast()方法来发送,不过该方法在android .50(api 21)中已经被deprecated,所以并不推荐使用。粘性广播一旦发送,便会一直滞留,当有匹配的广播接收器注册时,此接收器便会接收到此广播。可以使用removeStickyBroadcast()方法来移除。使用粘性广播需要获得BROADCAST_STICKY权限:
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
(4)系统广播
Android系统中内置了多种系统广播,基本上涉及到手机的基本操作都会发出相应的系统广播,如:手机网络状态变化、手机SMS短信、开机启动等。系统广播在系统内部特定事件发生时由系统发出,然后由对应的广播接收器接收。
(5)本地广播
上述广播都是系统全局的广播,在系统内的所有应用程序都有可能接收到,如此便会产生安全隐患。为此,Android在Support V4包增加了本地广播,使广播能够仅限于在当前App应用中发送和接收。本地广播的发送使用LocalBroadcastManager,即将发送普通广播时使用的sendBroadcast、registerReceive、unregisterReceiver替换为LocalBroadcastManager.getInstance(Context context)中对应的方法。具体如下:
函 数 | 作 用 |
LocalBroadcastManager.getInstance(context). registerReceiver(receiver,intentFilter) | 注册Receiver |
LocalBroadcastManager.getInstance(context). unregisterReceiver(receiver) | 注销Receiver |
LocalBroadcastManager.getInstance(context). sendBroadcast(intent) | 发送异步广播 |
LocalBroadcastManager.getInstance(context). sendBroadcastSync(intent) | 发送同步广播 |
后记:Broadcast作为Android四大组件之一,其主要作用是用于组件间的通信。Android中的Broadcast采用了典型发布—订阅型的观察者模式,其发送方与接收方是完全解耦的。发送方仅负责发送广播消息,而不关心接收方是否能够接收到,或者如何如理消息。Broadcast共有五种类型,分别为普通广播、有序广播、粘性广播、系统广播、本地广播。
转载至:http://blog.csdn.net/lyklykkk/article/details/55047218