一、广播的定义
四大组件之一
在Android中,Broadcast是一种广泛运用的在应用程序之间传递信息的机制,发送广播使用Intent,intent可以携带数据
有两个角色,广播的发送者和广播的接受者
二、广播的使用场景
<1>在Android不同组件之间的通信(应用内/不同应用之间)
<2>多线程通信
<3>与 Android 系统在特定情况下的通信 如:电话呼入时、网络可用时
三、广播的种类
1、 普通广播
继承实现BroadcastReceiver的,在onReceive(Context context, Intent intent)中通过Intent获取传递的数据
2、有序广播
需要在IntentFilter中设置优先级,android:priority=“100” 数字越大优先级越高。优先级高德先接受到广播并可以修改广播内容给低优先级的广播接受者。
继承实现BroadcastReceiver的,在onReceive(Context context, Intent intent)中通过Intent获取传递的数据,如果要修改数据可以通过:
Bundle bundle = new Bundle();
bundle.putString("order","我是一个有序的广播,我被修改了");
setResultExtras(bundle);
来修改数据
终止消息再传递: abortBroadcast();
3、粘性广播
Android 5.0(API 21)开始,因为安全性的问题,官方已经正式废弃了粘性广播
4、本地广播(只在应用内部使用)
5、系统广播(System Broadcast)
Android中内置了多个系统广播:只要涉及到手机的基本操作(如开机、网络状态变化、拍照等等),都会发出相应的广播
四、实现广播
1、静态注册
注册完成后就一直在运行
2、动态注册
跟随activity的生命周期
五、内部实现机制
AMS: 核心服务 负责启动四大组件,应用程序的管理、切换、调度
1、自定义广播接受者,复写onRecvice方法;
2、通过Binder机制向AMS(Activity Manager Service)进行注册;
3、广播发送者通过Binder机制向AMS发送广播
4、AMS查找符合相应条件(IntentFilter/Permission)的BroadcastReceiver,将广播发送到Broadcast(一般情况是Activity)相应的消息循环队列中;
5、消息循环执行此广播,回调BroadcastReceiver的onReceiver方法
六、LocalBroadcastManager(本地广播)
1、 只是在APP内部发送广播,不必担心数据泄露
2、 其他APP无法对你的APP发送该广播,不必担心安全漏洞
3、比全局广播更加高效
用法:
<1> 注册:LocalBroadcastManager.getInstance(this).registerReceiver(MyBroadcast, intentFilter);
<2> 发送:LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent("com.test.broadcast"));//发送本地广播
内部是通过Handler的方式来进行发送的
源码分析:(三个变量集合的含义如下)
//记录当前注册所有广播 主要用于销毁广播时使用
private final HashMap<BroadcastReceiver, ArrayList<ReceiverRecord>> mReceivers= new HashMap<>();
//记录当前拥有某Action的广播
private final HashMap<String, ArrayList<ReceiverRecord>> mActions = new HashMap<>();
//记录当前等待执行的广播
private final ArrayList<BroadcastRecord> mPendingBroadcasts = new ArrayList<>();
----------------------------------------------------------------------------------------------------------------
1、初始化LocalBroadcastManager
创建Handler对象
2、注册广播LocalBroadcastManager.getInstance(this) .registerReceiver(localBroadcast, intentFilter);
<1>将广播接受者和过滤器匹配,一个广播接受者可能有多个意图过滤。:
ReceiverRecord entry = new ReceiverRecord(filter, receiver);
ArrayList<ReceiverRecord> filters.add(entry);
<2>将匹配好的ReceiverRecord的集合filters分别放到mReceivers和mActions中
3、发送广播LocalBroadcastManager.getInstance(BroadcastActivity.this) .sendBroadcast(Intent);
<1>通过sendBroadcast中的intent获取到action对象
<2>通过action从集合mActions中获取到所有的广播接收者ArrayList<ReceiverRecord> entries
<3>循环所有的广播接受者,通过匹配sendBroadcast中的intent信息保存符合意图的广播接收者到集合 ArrayList<ReceiverRecord> receivers中
<4>将符合意图的广播接受者receivers和意图intent保存到BroadcastRecord类中
<5>将BroadcastRecord放到集合mPendingBroadcasts中
<6>使用handler发送一个空的消息
<7>在handler中接受消息并执行executePendingBroadcasts()方法。在该方法中循环mPendingBroadcast获取到保存的符合意图的所有的广播接受者receivers,循环调用广播接受者的onReceive(Context, intent)方法,从而就可以在实现的MyBroadcastReceiver中获取到intent信息
4、注销广播 LocalBroadcastManager.getInstance(this) .unregisterReceiver(MyBroadcast);
<1>使用unregisterReceiver(MyBroadcast)中的MyBroadcast来移除mReceivers中注册的所有广播接受者ArrayList<ReceiverRecord> filters
<2>循环所有的filters找到所有的action对象String action = filter.filter.getAction(j);
<3>循环移除action对应的ReceiverRecord
七、使用广播时出现异常:java.lang.InstantiationException: class has no zero argument constructor
解决:如果是静态广播注册方式、广播作为内部类来使用:广播内部类声明为static类型。