1.Android广播机制概述
Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器)。
(1)广播作为Android组件间的通信方式,可以使用的场景如下:
①同一app内部的同一组件内的消息通信(单个或多个线程之间);
②同一app内部的不同组件之间的消息通信(单个进程);
③同一app具有多个进程的不同组件之间的消息通信;
④不同app之间的组件之间消息通信;
⑤Android系统在特定情况下与App之间的消息通信。
(2)从实现原理看上,Android中的广播使用了观察者模式,基于消息的发布/订阅事件模型。因此,从实现的角度来看,Android中的广播将广播的发送者和接受者极大程度上解耦,使得系统能够方便集成,更易扩展。
具体实现流程要点粗略概括如下:
①广播接收者BroadcastReceiver通过Binder机制向AMS(Activity Manager Service)进行注册;
②广播发送者通过binder机制向AMS发送广播;
③AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到BroadcastReceiver(一般情况下是Activity)相应的消息循环队列中;
④消息循环执行拿到此广播,回调BroadcastReceiver中的onReceive()方法。
(3)由此看来,广播发送者和广播接收者分别属于观察者模式中的消息发布和订阅两端,AMS属于中间的处理中心。广播发送者和广播接收者的执行是异步的,发出去的广播不会关心有无接收者接收,也不确定接收者到底是何时才能接收到。显然,整体流程与EventBus非常类似。
(3)在上文说列举的广播机制具体可以使用的场景中,现分析实际应用中的适用性:
第①种情形:同一app内部的同一组件内的消息通信(单个或多个线程之间),实际应用中肯定是不会用到广播机制的(虽然可以用),无论是使用扩展变量作用域、基于接口的回调还是Handler-post/Handler-Message等方式,都可以直接处理此类问题,若适用广播机制,显然有些“杀鸡牛刀”的感觉,会显太“重”;
第②种情形:同一app内部的不同组件之间的消息通信(单个进程),对于此类需求,在有些教复杂的情况下单纯的依靠基于接口的回调等方式不好处理,此时可以直接使用EventBus等,相对而言,EventBus由于是针对统一进程,用于处理此类需求非常适合,且轻松解耦。可以参见文件《Android各组件/控件间通信利器之EventBus》。
第③④⑤种情形:由于涉及不同进程间的消息通信,此时根据实际业务使用广播机制会显得非常适宜。下面主要针对Android广播中的具体知识点进行总结。
2.要使用广播,需要以下步骤:
(1).定义广播接收器
/** * 定义一个广播接收器,继承BroadcastReceiver并重写onReceive(Context context, Intent intent)方法: */
public class MyBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, intent.getExtras().getString("msg"),
Toast.LENGTH_LONG).show();
}
}
(2)注册广播接收器
有两种方式注册广播接收器:静态注册和动态注册。通过静态方式注册的广播接收器叫常驻广播,通过动态方式注册的广播接收器叫非常驻广播。
①常驻广播:当你的应用程序关闭了,如果有广播信息来,你写的广播接收器同样的能接收到。
/** * 常驻广播就是在Androidmanifest.xml注册的广播 */
<receiver android:name="com.ui.broadcastreceiverdemo.MyBroadcastReceiver"
android:exported="false" >
<intent-filter>
<action android:name="Action.StaticBroadcastReceiver" />
</intent-filter>
</receiver>
②非常驻广播:当应用程序结束了,广播自然就没有了。
/** * 非常驻广播在代码中注册:registerReceiver(BroadcastReceiver receiver, IntentFilter filter) */
receiver = new MyBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("Action.DynamicBroadcastReceiver");
registerReceiver(receiver, intentFilter);
/** * 在组件销毁的时候注销广播 */
unregisterReceiver(receiver);
(3).向接收器发送广播
发送广播调用sendBroadcast(Intent intent)方法。可以使用显示Intent,也可以使用隐式Intent。需要注意的是,向动态广播接收器发送广播必须使用隐式Intent。
/** * 使用显示intent发送静态广播 */
Intent intent = new Intent(this, MyBroadcastReceiver.class);
intent.putExtra("msg", "IntentBroadcastReceiver");
sendBroadcast(intent);
/** * 使用隐式Intent发送静态广播 */
Intent staticIntent = new Intent(); staticIntent.setAction("Action.StaticBroadcastReceiver");
staticIntent.putExtra("msg","StaticBroadcastReceiver");
sendBroadcast(staticIntent);
/** * 使用隐式Intent发送动态广播 */
Intent dynamicIntent = new Intent(); dynamicIntent.setAction("Action.DynamicBroadcastReceiver");
dynamicIntent.putExtra("msg", "DynamicBroadcastReceiver");
sendBroadcast(dynamicIntent);
注意:通常情况下应该使用隐式intent发送广播。实际上由于广播的性质,即使广播接收器不存在,也可以发送广播,因为广播发送出去之后,广播发送者并不关心广播是否被接收。这一点与启动一个activity不一样。