Broadcast使用场景解读

《Broadcast使用场景解读》 BroadcastReceiver组件

在之前的一篇文章《基于场景解读Android四大组件》谈到BroadcastReceiver是Android提供给开发者的一个组件,主要用来完成前台和后台之前的通信,也就是Activity和Service之间的通信。今天我们继续通过使用场景来分析Android中的Broadcaster和BroadcastReceiver。

我们知道Android的底层使用了Linux内核,Linux下面提供了很多的IPC通信方式,比如消息,管道,共享内存,信号量,Socket等等。但是Android并没有采用Linux的几种IPC方案,而是使用了binder来完成进程之间的IPC。这主要是基于以下两点考虑:

  • 效率,其底层使用了共享内存机制,提高了数据读写的效率
  • 安全,从底层着手控制每个进程之间的访问权限,相比Linux在上层来控制访问权限要更加安全
那么binder又是如何在Android中使用的呢?主要有两种方式:
  • 采用代理模式,每个Client在访问Service之前都会获取一个Service的代理,然后通过这个代理来调用Service端提供的功能。比方说我们在Activity或者Service中通过getSystemService()获取到的XXXManager接口就属于这种。
  • 采用广播发送/接收的形式,也就是我们今天要讲的Broadcast和BroadcastReceiver,这种方式本质上属于消息订阅/发布的事件驱动流形式。
那么这两种形式有什么区别呢?
  • 代理模式一般用于点对点通信,也就是网络通信中的单播模式,优点是效率高,缺点是通信是即时发起的,同步调用。
  • 广播方式的话,效率相对低一些,但是通信是随时发起,异步调用。

这里引用老罗一篇博客《Android系统中的广播(Broadcast)机制》里面的描述会更清晰:

在Android系统中,为什么需要广播机制呢?广播机制,本质上它就是一种组件间的通信方式,如果是两个组件位于不同的进程当中,那么可以用Binder机制来实现,如果两个组件是在同一个进程中,那么它们之间可以用来通信的方式就更多了,这样看来,广播机制似乎是多余的。然而,广播机制却是不可替代的,它和Binder机制不一样的地方在于,广播的发送者和接收者事先是不需要知道对方的存在的,这样带来的好处便是,系统的各个组件可以松耦合地组织在一起,这样系统就具有高度的可扩展性,容易与其它系统进行集成。
在软件工程中,是非常强调模块之间的高内聚低耦合性的,不然的话,随着系统越来越庞大,就会面临着越来越难维护的风险,最后导致整个项目的失败。Android应用程序的组织方式,可以说是把这种高内聚低耦合性的思想贯彻得非常透彻,在任何一个Activity中,都可以使用一个简单的Intent,通过startActivity或者startService,就可以把另外一个Activity或者Service启动起来为它服务,而且它根本上不依赖这个Activity或者Service的实现,只需要知道它的字符串形式的名字即可,而广播机制更绝,它连接收者的名字都不需要知道。

关于Android Broadcast的使用这里不做介绍,我们这里只谈谈Broadcast的使用场景。目前在App开发中的消息全局通知方案有以下几种:系统广播,观察者和eventbus等第三方开源工具。观察者和eventbus都只能用于应用内的消息通信,他们之间的区别主要在于实现方式的不同。观察者是由用户通过handler自己实现一套,维护和扩展方便,但是一般不支持优先级和sticky等原生广播特性,而且随着业务逻辑复杂度增加,监听接口会迅速膨胀。eventbus等第三方开源工具功能使用简单,功能也要强大一些,支持优先级和sticky等原生广播特性。但是由于是使用第三方库所以在不了解其实现原理的情况下bug调试跟踪会变得困难,而且更新库(接口或者一些属性有变动的话)可能会影响到代码的大面积改动。broadcast不仅支持应用内通信也支持不同应用进程之间的通信。但是由于其底层使用binder来实现,所以效率上与前两者相比要低一些。当然broadcast最大的优势还是在对系统事件的监听上,这是其他两个方案没法办到的。所以关于消息通信方案的选择上,需要根据自己的需求来选择合适的方案。当需要App应用内通信时,优先选择观察者或者Eventbus,当需要进程间通信或者监听系统广播事件时,选择Broadcast。另外再提一下LocalBroadcastManager这个类,它是一个本地广播管理器,估计是Android考虑到原生Broadcast的效率问题而提供的一个轻量级的广播。它主要是解决App应用内通信的问题,采用handler实现,跟观察者的实现方案类似,有兴趣的可以去看下它的源码。

Android提供了BroadcastReceiver这个组件来帮助我们监听广播消息,这里我们来看下BroadcastReceiver的使用场景:
  • App全局监听,这种主要用于在AndroidManifest中静态注册的广播接收器,一般我们在收到该消息后,需要做一些相应的动作,而这些动作与当前App的组件,比如Activity或者Service的是否运行无关,比如我们在集成第三方Push SDK时,一般都会添加一个静态注册的BroadcastReceiver来监听Push消息,当有Push消息过来时,会在后台做一些网络请求或者发送通知等等。
  • 组件局部监听,这种主要是在Activity或者Service中使用registerReceiver()动态注册的广播接收器,因为当我们收到一些特定的消息,比如网络连接发生变化时,我们可能需要在当前Activity页面给用户一些UI上的提示,或者将Service中的网络请求任务暂停。所以这种动态注册的广播接收器适合特定组件的特定消息处理。
关于BroadcastReceiver使用需要注意的几点:
  • onReceive中不能执行耗时操作,如果耗时超过10s会弹出ANR。
  • onReceive中context参数,如果是静态注册的广播,context为ReceiverRestrictedContext,所在如果在这里要启动一个Activity的话(调用startActivity),需要在intent中添加Intent.FLAG_ACTIVITY_NEW_TASK;如果是动态注册的广播,context为当前注册时所在的组件,比如Activity或者Service。
  • 监听系统广播,需要在AndroidManifest中申请权限,此外,Android高版本系统对于一些重要的系统广播,比如开机启动,网络连接,电量变化,锁屏等做了限制,如果需要监听这些广播,需要做系统兼容性处理。
  • 普通广播的广播接收器是并行无序执行的,有序广播的广播接收器按照广播优先级串行执行
    原文作者:codeKeeper
    原文地址: https://www.jianshu.com/p/5a983578418e
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞