注册

面试官直问:你晓得什么是有序广播?

当面试官直接问你该问题时,对我们考察的是看我们否了解广播相关的知识

这里我们必须了解广播的基本知识和原理,接下来对该问题进行回答解析。

问题正解

  1. 广播是什么?

  • 广播是一种广泛运用的在应用程序之间传输信息的机制,Android 主要是将系统运行时的各种“事件”通知给其他应用,因此设计了多种广播。广播机制最大的特征就是发送方并不关注接收方是否接到数据,也不关注接收方是如何处理数据的。
  • Android 中的每个应用程序都可以对自己有利的广播进行注册,这样程序就只会接收到自己所关心的广播内容,这些广播可能是来自于系统的,也可能是来自于其他应用程序的,前者是系统广播,后者是自定义广播。广播在具体的项目中应用场景并不多,但一旦使用会使得程序变得精简很多。
  • 安卓的广播原理,BroadCastReceiver是对分发出来的Broadcast 进行过滤接受并响应的一类组件,属于Android四大组件之一,主要用于接收系统或者app发送的广播事件。在我们的项目中常常使用广播接收者接收系统通知,比如开机启动、低电量、外播电话、锁屏、sd挂载等。 如果我们需要做的是播放器,那么监听到用户锁屏后我们应该将播放状态的暂停。android的四大组件核心就是为了实现移动、或者讲是嵌入式设备上的架构,它们之间有时候是一种相互依赖的关系, 有时候又是一种补充关系,引入广播机制可以极大方便几大组件的信息和数据交流。广播有利于程序间交流消息,例如在自己的应用程序内监听系统来电。
  1. 如何使用广播?

  • 自定义一个BroadcastReceiver,在onReceive()方法中完成广播要处理的事务,比如这里的提示Toast信息。
public class MyReceiver extends BroadcastReceiver{
   @Override
   public void onReceive(Context context, Intent intent) {
       Toast.makeText(context,"你的网络状态发生改变~",Toast.LENGTH_SHORT).show();
  }
}
  • MainActivity.java中动态注册广播:
public class MainActivity extends AppCompatActivity {

   MyBRReceiver myReceiver;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       //核心部分代码:
       myReceiver = new MyReceiver();
       IntentFilter itFilter = new IntentFilter();
       itFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
       registerReceiver(myReceiver, itFilter);
  }

   //别忘了将广播取消掉哦~
   @Override
   protected void onDestroy() {
       super.onDestroy();
       unregisterReceiver(myReceiver);
  }
}
  • 我们也可以在AndroidManifest.xml中静态注册:
<receiver android:name=".MyReceiver">
   <intent-filter>
       <action android:name = "android.net.conn.CONNECTIVITY_CHANGE">
   </intent-filter>
</receiver>
  • 动态注册的广播接收器可以自由的控制注册、取消,有很大的灵活性。但是只能在程序启动之后才能收到广播,此外,广播接收器的注销是在onDestroy()方法中的。所以广播接收器的生命周期是和当前活动的生命周期一致。
  • 静态注册的广播不受程序是否启动的约束,当应用程序关闭之后,还是能接收到广播。
  1. 有序广播、无序广播。

  • 按照广播的属性区分,广播分两种:有序广播和无序广播。
  • 无序广播:又叫普通广播,完全异步,不会被某个广播接收者终止,逻辑上可以被任何广播接收者接收到,如果在广播发出之后,所有的广播接收器几乎都会在同时接收到这条广播消息,因此它们之间没有任何先后顺序可言。优点是效率较高。缺点是一个接收者不能将处理结果传递给下一个接收者,并无法停止广播intent的传播。Context.sendBroadcast() 发送的是普通广播,所有订阅者都有机会获得并进行处理。
  • 有序广播:按照被接收者的优先级顺序,在被接收者中依次传播。比如有三个广播接收者A,B,C,优先级顺序是A > B > C。那这个消息先传递给A,再传给B,最后传给C。因此常常需要在AndroidManifest.xml 中进行注册,优先级别声明在intent-filter 元素的android:priority 属性中,数值越大优先级别越高,取值范围:-1000 到1000,优先级别也可以调用IntentFilter 对象的setPriority()进行设置。
  • 有序广播的接收者可以停止广播的传播,广播的传播一旦停止,后面的接收者就无法接收到广播,有序广播的接收者可以将数据传递给下一个接收者,如:A 得到广播后,可以往它的结果对象中存入数据,当广播传给B 时,B 可以从A 的结果对象中得到A 存入的数据。Context.sendOrderedBroadcast() 发送的是有序广播。Bundlebundle = getResultExtras(true))可以获取上一个接收者存入在结果对象中的数据。
  1. Android中常用的系统广播。

  • 系统广播是指系统作为广播的发送方,发出来的广播,我们可以在应用程序中通过监听这些广播来得到各种系统的状态信息。
//关闭或打开飞行模式时的广播
Intent.ACTION_AIRPLANE_MODE_CHANGED;

//充电状态,或者电池的电量发生变化。电池的充电状态、电荷级别改变,不能通过组建声明接收这个广播,只有通过Context.registerReceiver()注册
Intent.ACTION_BATTERY_CHANGED;

//表示电池电量低
Intent.ACTION_BATTERY_LOW;

//表示电池电量充足,即从电池电量低变化到饱满时会发出广播
Intent.ACTION_BATTERY_OKAY;

//在系统启动完成后,这个动作被广播一次(只有一次)。
Intent.ACTION_BOOT_COMPLETED;

//按下照相时的拍照按键(硬件按键)时发出的广播
Intent.ACTION_CAMERA_BUTTON;

//当屏幕超时进行锁屏时,当用户按下电源按钮,长按或短按(不管有没跳出话框),进行锁屏时,android系统都会广播此Action消息
Intent.ACTION_CLOSE_SYSTEM_DIALOGS;

//设备当前设置被改变时发出的广播(包括的改变:界面语言,设备方向,等,请参考Configuration.java)
Intent.ACTION_CONFIGURATION_CHANGED;

//设备日期发生改变时会发出此广播
Intent.ACTION_DATE_CHANGED;
//用户重新开始一个包,包的所有进程将被杀死,所有与其联系的运行时间状态应该被移除,包括包名(重新开始包程序不能接收到这个广播)
Intent.ACTION_PACKAGE_RESTARTED;

//插上外部电源时发出的广播
Intent.ACTION_POWER_CONNECTED;

//已断开外部电源连接时发出的广播
Intent.ACTION_POWER_DISCONNECTED;

Intent.ACTION_PROVIDER_CHANGED;//

//重启设备时的广播
Intent.ACTION_REBOOT;

//屏幕被关闭之后的广播
Intent.ACTION_SCREEN_OFF;

//屏幕被打开之后的广播
Intent.ACTION_SCREEN_ON;

//关闭系统时发出的广播
Intent.ACTION_SHUTDOWN;

//时区发生改变时发出的广播
Intent.ACTION_TIMEZONE_CHANGED;

//时间被设置时发出的广播
Intent.ACTION_TIME_CHANGED;

//广播:当前时间已经变化(正常的时间流逝), 当前时间改变,每分钟都发送,不能通过组件声明来接收
,只有通过Context.registerReceiver()方法来注册
Intent.ACTION_TIME_TICK;

//一个用户ID已经从系统中移除发出的广播
Intent.ACTION_UID_REMOVED;

  1. 广播的原理。

  • 从实现原理看上,Android中的广播运用了观察者模式,基于消息的发布/订阅事件模型。因此,从实现的角度来看,Android中的广播将广播的发送者和接受者进行了极大程度上解耦,使得系统能够容易集成,更易扩展。具体实现流程要点如下:

    1.广播接收者BroadcastReceiver通过Binder机制向AMS(Activity Manager Service)进行注册;

    2.广播发送者通过binder机制向AMS发送广播;

    3.AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到BroadcastReceiver(一般情况下是Activity)相应的消息循环队列中;

    4.消息循环执行得到此广播,回调BroadcastReceiver中的onReceive()方法。 对于不同的广播类型,以及不同的BroadcastReceiver注册方式,具体实现上会有不一样。

  • 广播发送者和广播接收者分别属于观察者模式中的消息发布和订阅两端,AMS是处理中心。广播发送者和广播接收者的执行是异步的,发出去的广播不会关心有无接收者接收,也不确定接收者到底是何时才能接收到。
  • 对Binder和AMS知识不熟悉的话可以翻阅前面讲解Binder和AMS的原理章节,学习其中的内容。

总结

有序广播是广播中比较特殊的类型,广播接受者接收广播的时间是不一样的,它们之间是有先后顺序的。系统通过priority的大小来排列优先级别,数值越大级别越高。广播的传播可以依照优先级别逐个传递下去,也可以在某一接收者处中断,那样后面的接收者就无法收到广播。


作者:派大星不吃蟹
链接:https://juejin.cn/post/7256438624602669111
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册