LocalBroadcastManager
LocalBroadcastReceiver应该主要是借助LocalBroadcastManager来实现,大概看了一下LocalBroadcastManager代码,只有两百来行,非常之简单。可以仔细看看,然后可以举一反三地推测组件级的Broadcast到底怎么实现。看看这个类有哪些东西:
两个静态内部类
1.ReceiverRecord
ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) {
filter = _filter;
receiver = _receiver;
}
2.BroadcastRecord
BroadcastRecord(Intent _intent, ArrayList<ReceiverRecord> _receivers) {
intent = _intent;
receivers = _receivers;
}
几个成员
private final HashMap<BroadcastReceiver, ArrayList<IntentFilter>> mReceivers
private final HashMap<String, ArrayList<ReceiverRecord>> mActions //action 为key
private final ArrayList<BroadcastRecord> mPendingBroadcasts
几个重要方法
1.public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter)
把注册的广播放入mReceivers中。
2.public boolean sendBroadcast(Intent intent)
只看intent只包含action的部分。
- 从mActions中取出这个intent包含的action对应的value–ArrayList entries
- 分解 组装,将需要接受这个action的broadcast对象放入mPendingBroadcasts 集合中(这一步较为复杂,大概应该是做了这个操作)
- 发handler(主线程handler),handler调用executePendingBroadcasts()
- executePendingBroadcasts()中第二轮遍历(先取出每一个BroadcastRecord,再取出每个BroadcastRecord中的每个receiver),依次调用每个receiver的onReceiver方法,将context和intent传入
总结
可见,这个机制主要就是借助一个静态单例类LocalBroadcastManager。静态保证了他一旦创建就基本上与application一样的生命周期。他持有 所有register到他里面的broadcast的引用。因此需要利用他发广播时,就可以立即拿到这个broadcast引用 调用 这个broadcast对象的onReceive方法。
- 思考1:是不是我们随便定义一个 相似的静态单例对象,都可以实现类似的解耦套路?
- 思考2:LocalBroadcastManager内部在sendbroadcast时,通过Handler来 间接调用executePendingBroadcasts。为何不去掉Handler这个机制,在sendbroadcast时直接调用executePendingBroadcasts
因为事实上所有的操作都在主线程中。 - 思考3:既然使用到了静态单例类,就要考虑到潜在的内存泄露。看下引用链:LocalBroadcastManager – broadcastReceiver – Nothing?
普通广播之所以要unRegister是因为context.registerBroadcastReceiver时,将context引用传给了这个broadcastReceiver,因此引用链是 ams–broadcastreceiver—activity。因为广播持有了activity,所以不解注册,会造成activity泄露。而这个局部广播没有持有activity?因此是不是不需要unRegister?