Broadcast
Broadcast概念
1. 定义
Broadcast(广播)是一个全局的监听器,属于Android四大组件之一,是一种广泛运用的在应用程序(APP)之间传输信息的机制。而BroadcastReceiver(广播接收器)是对发送出来的 广播进行过滤接受并响应的一类组件。
2. 应用场景
- Android不同组件间的通信(同一应用内 / 不同应用间)
- 多线程通信
- 与 Android 系统在特定情况下的通信
- 接收系统的状态信息
3. 生命周期
BroadcastReceiver 生命周期非常短暂,发送广播时创建,onReceive()方法结束之后销毁
4. 使用要素
- Broadcast (广播) – 用于发送广播
- BroadcastReceiver (广播接收器) – 用于接受广播
- Intent (意图) – 用于保存广播相关信息的媒介
Broadcast类型
1. 广播类型
- 从类型上可以分为有序广播和标准广播两大类
- 从广播接收器的注册方法上可以分为静态注册和动态注册
- 从发送方式上可以分为普通广播、有序广播、粘性广播、本地广播…
- 从所属队列上可以分为前台广播、后台广播
2. 事例
- 有序广播
- 标准广播
3. 注册
-
静态注册:通过新建Broadcast Receiver文件AndroidStudio会自动在AndroidManifest文件中注册
<receiver android:name=".MyReceiver" android:enabled="true" android:exported="true"> </receiver>
Broadcast Receiver文件为
public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context,"MyReceiver",Toast.LENGTH_SHORT).show(); } }
然后在需要发送广播的地方进行
//静态注册 Intent intent1 = new Intent(); intent1.setClassName(getPackageName(),"com.example.broadcasttest.MyReceiver"); sendBroadcast(intent1);
然后在MainActivity中进行实例化
private MyReceiver myReceiver; myReceiver = new MyReceiver();
-
动态注册:和静态广播的创建BroadcastRecevier类似,新建一个BroadcastReceiver子类,通过extends BroadcastReceiver类
private class LightReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { /*Bundle extras = intent.getExtras(); Light light = (Light) extras.get("light1");*/ Light light = intent.getParcelableExtra("light1"); Log.d(TAG, "onReceive: " + light); } }
发送广播
//动态注册 Intent intent = new Intent(); intent.setAction("com.example.broadcasttest.LightService"); intent.putExtra("light1",new Light("111",true)); sendBroadcast(intent);
由于动态广播是动态注册的,需要在类中进行初始化的声明,和AndroidManifest.xml中的 类似,在onCreate中实现注册:
IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("com.example.broadcasttest.LightService"); mLightReceiver = new LightReceiver(); registerReceiver(mLightReceiver,intentFilter);
在onDestory中进行反注册
unregisterReceiver(mLightReceiver);
4. Android的序列化
在这里有必要说明一下Android的序列化,不同于Java的实现Serializable接口,Android实现的是Parcelable接口
public class Light implements Parcelable {
private String frequency;
private boolean state;
public Light(String frequency, boolean state) {
this.frequency = frequency;
this.state = state;
}
protected Light(Parcel in) {
frequency = in.readString();
state = in.readByte() != 0;
}
public static final Creator<Light> CREATOR = new Creator<Light>() {
@Override
public Light createFromParcel(Parcel in) {
return new Light(in);
}
@Override
public Light[] newArray(int size) {
return new Light[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(frequency);
dest.writeByte((byte) (state ? 1 : 0));
}
@Override
public String toString() {
return "Light{" +
"frequency='" + frequency + '\'' +
", state=" + state +
'}';
}
}
这里就不需要实现构造器,实现get,set方法,只需要实现Parcelable接口的方法即可。在定义实体类的时候直接通过如下代码实现
new Light("111",true)
当在Intent中获取时,只需要调用getParcelableExtra方法即可直接返回实体类数据。
5. 注册和反注册
- 注册与反注册广播方法要成对出现,重复注册、重复注销也不允许
- 调用Context注册,就要用Context反注册。而不能直接调用unregisterReceiver(mReceiver)
5. unregisterReceiver(mReceiver)的作用:在Android开发中,在不进行反注册时,在关闭应用后,广播会一直处于接受状态,导致占用内存越来越大;而进行反注册后,则会结束广播,使得内存回收。
6. 有序广播与无序广播
7. 广播超时
- 并行队列中的广播的分发是循环取出每一个广播,直接分发,不需要等待客户端的反馈,所以并行队列中的广播分发很快
- 串行队列中的广播必须要等待前面的BroadcastReceiver执行完成后才会分发下一个,如果客户端的BroadcastReceiver运行在主线程,但是主线程又很繁忙,就有可能导致超时。
- 并行队列中的广播不存在超时概念,只有串行队列中的广播才会超时
- 存在静态注册的广播接收器的普通广播或有序广播
- 存在动态注册的广播接收器的有序广播
8. 本地广播LocalBroadcastReceiver
- LocalBroadcastReceiver与BroadcastReceiver区别:
- BroadcastReceiver是针对应用间、应用与系统间、应用内部进行通信的一种方式
- LocalBroadcastReceiver仅在自己的应用内发送接收广播,也就是只有自己的应用能收到,数据更加安全广播只在这个程序里,而且效率更高。
- LocalBroadcastReceiver不能静态注册,只能采用动态注册的方式。
- 使用:
- 发送广播同时创建BroadcastReceiver:
LocalReceiver mLocalReceiver = new LocalReceiver(); Intent intent = new Intent(); intent.setAction(ACTION); LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
- 注册广播:
IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(ACTION); LocalBroadcastManager.getInstance(this) .registerReceiver(mLocalReceiver, intentFilter);
- 反注册广播
LocalBroadcastManager.getInstance(this).unregisterReceiver(mLocalReceiver);
Broadcast时序
- 普通广播(Normal Broadcast)
- 无视优先级,动态广播接收器优先于静态广播接收器
- 同优先级的同类广播接收器:
- 静态:先扫描的优先于后扫描的
- 动态:先注册的优先于后注册的
- 有序广播(Ordered Broadcast)
- 发送出去的广播被广播接收者按照先后顺序接收
- 优先级高的先接收(不分静态和动态)
- Priority属性相同者,动态注册的广播优先
- 特点:
- 接收广播按顺序接收
- 先接收的BroadcastReceiver可以对广播进行截断,那么后接收的BroadcastReceiver不能再接收到此广播
- 先接收的BroadcastReceiver可以对广播进行修改,那么后接收的BroadcastReceiver将接收到被修改后的广播
- 发送出去的广播被广播接收者按照先后顺序接收
Broadcast参数
-
Intent putExtra
Intent intent = new Intent(); intent.setAction("com.example.broadcasttest.LightService"); intent.putExtra("light1",new Light("111",true)); sendBroadcast(intent);
-
Intent getExtra
Light light = intent.getParcelableExtra("light1");