版权声明:安全
本帐号发布文章均来自公众号,承香墨影(cxmyDev),版权归承香墨影全部。异步
未经容许,不得转载。oop
最开始的时候,Android 下的 Broadcast 都是全局的,发出去的广播,只要有匹配的接收者,就能够收到广播。线程
而在 Support v4 : 21 以后,提供了一种新的 Broadcast 的形式,就是 LocalBroadcast,它主要用于在同一个应用中,不一样组件之间,发送和接收 Broadcast。设计
BroadcastReceiver 在设计之初,就是想从全局的角度去设计一个方便不一样应用程序之间进行通讯的组件。而这样的一个开放的设计,对单个应用程序而言,BroadcastReceiver 是存在各类安全问题的。code
而 LocalBroadcast 就是由于这个而存在的,顾名思义,它就是为了在同一个应用程序内,进行通讯的组件。它经过 LocalBroadcastManager (如下简称 LBM),来实现注册、解注、发送广播等操做。cdn
它和原有的 BroadcastReceiver 相比而言,有什么好处:对象
LocalBroadcast 经过 LocalBroadcastManager 来管理,在 LBM 中,提供了普通广播使用的对应的 API,经过 LBM 中提供的 API,就能够完成对本地广播的操做,使用方式和普通广播无异。blog
LBM 是一个单例对象,能够经过 LocalBroadcastManager.getInstance(Context)
方法获取到。生命周期
LBM 的使用,其实没什么好说的,直接上例子。
首先,定义一个 BroadcastReceiver ,而后在一个 Activity 的生命周期内,分别注册和解注它,而后监听一个按钮的点击,用于发送 LocalBroadcast。
正常来讲,使用 sendBroadcast()
是一个异步的操做,它不会堵塞住线程,同时 LBM 也提供了对应的同步操做方法,sendBroadcastSync()
。
接下来就来探究一下 LBM 的实现原理。自己普通的广播为了实现跨进程,使用了 Binder 机制,而 LocalBroadcast 上面介绍的会比普通广播跟高效,那么接下来就看看 LBM 的实现原理,是如何作到更高效的。
LBM 自己是一个单例的实现,也就是说,在当前进程的生命周期内只有一个 LBM 对象。
直接看 LBM 的构造方法。
能够看到,在其私有的构造方法中,实际上建立了一个基于主线程的 Looper 的 Handler,在这个 Handler 中,调用 executePendingBroadcasts()
方法,从方法名上,猜想这个方法是对接收到的广播进行处理。
接下来就来证明咱们的猜想。
先看看注册接收者的 registerReceiver() 方法。
能够看到,在registerReceiver()
方法中,主要是操做了两个对象:mReceivers、mActions,它们都是 HashMap 类型的集合。
mReceivers 主要用于维护一个 BroadcastReceiver 对象和它的 IntentFilter 对象的对应关系。主要是为了方便在 unregisterReceiver()
方法中,快速的移除它,而且它也做为同步对象锁限制一些行为的同步访问。
而 mActions 则维护了一个以 action 为 key,ReceiverRecord 对象为 value 的对应关系。这样能够方便经过 action 找到与之匹配的 ReceiverRecord。而 ReceiverRecord 是一个内部类,主要用于存储 receiver 和 IntentFilter。
再来看看 unregisterReceiver()
方法,其实很是的简单,它只是按照条件,移除了 mReceivers 和 mActions 两个对象中存储的 BroadcastReceiver。
最关键的 sendBroadcast()
方法,看看它最终是如何发送这个 LocalBroadcast 的。
虽然看着挺多代码的,可是实际上它的处理方式很简单。先从 mActions 中取出对应的 ReceiverRecord 对象,而后在根据 IntentFilter 匹配出符合条件的 Receiver,再将其保存到 mPendingBroadcasts 对象中,最后发送一个 MSG_EXEC_PENDING_BROADCASTS 的消息给 mHandler。
后续咱们就已经知道了,mHandler 接收到 MSG_EXEC_PENDING_BROADCASTS 消息以后,就会去执行 executePendingBroadcasts()
方法。
到这里就清晰了,它会将以前暂存在 mPendingBroadcasts 中的对象所有取出来,而后循环调用其 onReceiver() 方法,将其消费掉,完成这次广播的发送。
那再看看同步方法 sendBroadcastSync() 方法中是如何实现的,
能够看到,它其实是调用 sendBroadcast() 以后,当即调用 executePendingBroadcasts() 方法去执行。这样由于在其中有同步对象锁,而且也有对 mPendingReceivers 中数量的校验,因此最终,发送给 mHandler 的消息执行的 executePendingBroadcasts() 方法的时候,对应的 mPendingReceivers 已经被消费掉清空了,就会被过滤掉,其实是一次无心义的调用。
到此,基本上就已经彻底了解了 LocalBroadcastManager 的全部细节,它之因此比普通广播跟高效,是由于其中并无利用 Binder ,而是借助 Handler 来实现应用内的通讯,天然安全性更好,效率更高。
其实 LocalBroadcastManager 实现的效果相似一个 EventBus 的效果,更多的状况下,仍是推荐使用相似 EventBug 这类成熟的开源库来完成咱们应用内通讯的需求。固然,LocalBroadcastManager 的思路仍是有值得咱们借鉴的地方的。