- CompoundButton 源码分析
- LinearLayout 源码分析
- SearchView 源码解析
- LruCache 源码解析
- ViewDragHelper 源码解析
- BottomSheets 源码解析
- Media Player 源码分析
- NavigationView 源码解析
- Service 源码解析
- Binder 源码分析
- Android 应用 Preference 相关及源码浅析 SharePreferences 篇
- ScrollView 源码解析
- Handler 源码解析
- NestedScrollView 源码解析
- SQLiteOpenHelper/SQLiteDatabase/Cursor 源码解析
- Bundle 源码解析
- LocalBroadcastManager 源码解析
- Toast 源码解析
- TextInputLayout
- LayoutInflater 和 LayoutInflaterCompat 源码解析
- TextView 源码解析
- NestedScrolling 事件机制源码解析
- ViewGroup 源码解析
- StaticLayout 源码分析
- AtomicFile 源码解析
- AtomicFile 源码解析
- Spannable 源码分析
- Notification 之 Android 5.0 实现原理
- CoordinatorLayout 源码分析
- Scroller 源码解析
- SwipeRefreshLayout 源码分析
- FloatingActionButton 源码解析
- AsyncTask 源码分析
- TabLayout 源码解析
3. 源码解析
3.1 LocalBroadcastManager 原理概要
LocalBroadcastManager 使用单例模式对象,初始化时会在内部初始化一个 Handler 对象用来接受广播。注册广播时,会将自定义的 BroadcastReceiver 对象和 IntentFilter 对象保存到 HashMap 中。发送广播时,则根据 IntentFilter 的 Action 值从已保存的 HashMap 找到对应接受者,并发送 Handler 消息去执行 receiver 的 onReceive 方法。
LocalBroadcastManager 核心代码为以下四个函数。
- registerReceiver(BroadcastReceiver receiver, IntentFilter filter) //注册广播函数
- unregisterReceiver(BroadcastReceiver receiver) //取消注册函数
- sendBroadcast(Intent intent) //发送广播
- executePendingBroadcasts() //处理接受到的广播
3.2 LocalBroadcastManager 基本数据结构
LocalBroadcastManager 需要保存三样东西,一个是 mReceivers , 用来保存已注册的自定义的 receiver 和 intentFilter。一个是 mActions 键值对,保存 action 和 ReceiverRecord 列表的键值对。一个是 mPendingBroadcasts , 用来保存待通知的 receiver 对象。
//注册广播 Record 类 private static class ReceiverRecord { final IntentFilter filter; final BroadcastReceiver receiver; boolean broadcasting; ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) { filter = _filter; receiver = _receiver; } ... } private final HashMap<BroadcastReceiver, ArrayList<IntentFilter>> mReceivers = new HashMap<BroadcastReceiver, ArrayList<IntentFilter>>(); private final HashMap<String, ArrayList<ReceiverRecord>> mActions = new HashMap<String, ArrayList<ReceiverRecord>>(); private final ArrayList<BroadcastRecord> mPendingBroadcasts = new ArrayList<BroadcastRecord>(); //待广播的 Record 类 private static class BroadcastRecord { final Intent intent; final ArrayList<ReceiverRecord> receivers; BroadcastRecord(Intent _intent, ArrayList<ReceiverRecord> _receivers) { intent = _intent; receivers = _receivers; } }
3.3 注册广播
将需要注册的 receiver 对象和该 receiver 需要监听的 filter 保存到 mReceivers 和 mPendingBroadcasts 中。
/** * Register a receive for any local broadcasts that match the given IntentFilter. * * @param receiver The BroadcastReceiver to handle the broadcast. * @param filter Selects the Intent broadcasts to be received. * * @see #unregisterReceiver */ public void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { synchronized (mReceivers) { ReceiverRecord entry = new ReceiverRecord(filter, receiver); ArrayList<IntentFilter> filters = mReceivers.get(receiver); if (filters == null) { filters = new ArrayList<IntentFilter>(1); mReceivers.put(receiver, filters); //保存 receiver 和 filter 到 List } filters.add(filter); for (int i=0; i<filter.countActions(); i++) { String action = filter.getAction(i); ArrayList<ReceiverRecord> entries = mActions.get(action); if (entries == null) { entries = new ArrayList<ReceiverRecord>(1); mActions.put(action, entries); //保存到 action 和 ReceiverRecord 到 HashMap } entries.add(entry); } } }
3.4 取消广播注册
根据 receiver 对象移除 mReceivers 和 mPendingBroadcasts 中对应的对象。
/** * Unregister a previously registered BroadcastReceiver. All * filters that have been registered for this BroadcastReceiver will be * removed. * * @param receiver The BroadcastReceiver to unregister. * * @see #registerReceiver */ public void unregisterReceiver(BroadcastReceiver receiver) { synchronized (mReceivers) { //从 mReceivers 中移除 ArrayList<IntentFilter> filters = mReceivers.remove(receiver); if (filters == null) { return; } for (int i=0; i<filters.size(); i++) { IntentFilter filter = filters.get(i); for (int j=0; j<filter.countActions(); j++) { String action = filter.getAction(j); ArrayList<ReceiverRecord> receivers = mActions.get(action); if (receivers != null) { for (int k=0; k<receivers.size(); k++) { if (receivers.get(k).receiver == receiver) { receivers.remove(k); k--; } } if (receivers.size() <= 0) { mActions.remove(action); //从 mActions 中移除 } } } } } }
3.5 通过 Handler 发送广播
发送广播时,先根据 intent 中的 action 到 mActions 中找到对应的记录,然后再完整匹配 filter 里面的各个字段,若匹配成功,则将对应的 receiver 添加的 mPendingBroadcasts 列表中,等待 handler 对象的 handleMessage() 方法处理。
/** * Broadcast the given intent to all interested BroadcastReceivers. This * call is asynchronous; it returns immediately, and you will continue * executing while the receivers are run. * * @param intent The Intent to broadcast; all receivers matching this * Intent will receive the broadcast. * * @see #registerReceiver */ public boolean sendBroadcast(Intent intent) { synchronized (mReceivers) { final String action = intent.getAction(); final String type = intent.resolveTypeIfNeeded( mAppContext.getContentResolver()); final Uri data = intent.getData(); final String scheme = intent.getScheme(); final Set<String> categories = intent.getCategories(); ... //根据 intent 的 action 寻找 ReceverRecord ArrayList<ReceiverRecord> entries = mActions.get(intent.getAction()); if (entries != null) { ArrayList<ReceiverRecord> receivers = null; for (int i=0; i<entries.size(); i++) { ReceiverRecord receiver = entries.get(i); //相同的 receiver,只添加一次 if (receiver.broadcasting) { continue; } int match = receiver.filter.match(action, type, scheme, data, categories, "LocalBroadcastManager"); if (match >= 0) { if (receivers == null) { receivers = new ArrayList<ReceiverRecord>(); } receivers.add(receiver); //标记为已添加,待广播状态 receiver.broadcasting = true; } else { ... } } if (receivers != null) { //receivers 添加完成后,将 broadcasting 状态回归 for (int i=0; i<receivers.size(); i++) { receivers.get(i).broadcasting = false; } //添加到待广播列表 mPendingBroadcasts.add(new BroadcastRecord(intent, receivers)); //若无正在处理的消息,则 handler 发送广播消息 if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) { mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS); } return true; } } } return false;
3.6 Handler 接受和消费广播
在 handler 对象的 handleMessage() 方法中遍历 mPendingBroadcasts 列表,依次循环调用其中的 onReceive() 方法,并将 intent 中的数据传入,从而消费广播信息。
private LocalBroadcastManager(Context context) { mAppContext = context; mHandler = new Handler(context.getMainLooper()) { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_EXEC_PENDING_BROADCASTS: executePendingBroadcasts(); break; default: super.handleMessage(msg); } } }; } private void executePendingBroadcasts() { while (true) { BroadcastRecord[] brs = null; synchronized (mReceivers) { final int N = mPendingBroadcasts.size(); if (N <= 0) { return; } //拷贝数据到 brs 数组 brs = new BroadcastRecord[N]; mPendingBroadcasts.toArray(brs); mPendingBroadcasts.clear(); } for (int i=0; i<brs.length; i++) { BroadcastRecord br = brs[i]; for (int j=0; j<br.receivers.size(); j++) { //循环数组里的内容,调用其 onReceive 方法,消费广播内容 br.receivers.get(j).receiver.onReceive(mAppContext, br.intent); } } }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论