Android本地广播LocalBroadcastManager使用
16lz
2021-01-23
文章目录
- LocalBroadcastManager 简介
- LocalBroadcastManager使用
- LocalBroadcastManager 源码分析
LocalBroadcastManager 简介
学习Android的同鞋一定知道四大组件,四大组件有:
四大组件中的BroadcastReceiver是全局广播,即发送广播时可能被多个App接收到,有时候从安全角度考虑,为了数据的安全传递,是不是有办法避免被多个App接收广播,于是有了本地广播,本地广播只会在自己的App内传播,用于在同一个应用内的不同组件间发送Broadcast进行通信。使用本地广播,需要用到support库中的LocalBroadcastManager。
LocalBroadcastManager使用
这里先列出LocalBroadcastManager中常用的方法:
LocalBroadcastManager中方法 | 说明 |
---|---|
getInstance(Context context) | 获取本地广播实例 |
registerReceiver(BroadcastReceiver receiver, IntentFilter filter) | 注册广播 |
unregisterReceiver(BroadcastReceiver receiver) | 解注册 |
sendBroadcast(Intent intent) | 发送广播(内部使用Handler,保证onReceive在主线程中调用) |
sendBroadcastSync(Intent intent) | 同步发送广播,如果消息队列中消息太多,会导致广播接收者接收广播太慢,可使用这个方法同步发送广播 |
- 获取LocalBroadcastManager对象
LocalBroadcastManager被设计为一个单例类,通过getInstance
方法获取实例,参数需要一个上下文对象
// javaLocalBroadcastManager localManager= LocalBroadcastManager.getInstance(mContext);
// kotlinval localManager = LocalBroadcastManager.getInstance(mContext)
- 注册观察者
和全局广播的思想一样,如果要接收广播,那么需要先注册一个广播,才能接收到匹配的广播。本地广播不能通过在AndroidManifest文件中静态声明注册,只能通过动态注册的方法注册,这里注册时需要调用registerReceiver
方法,需要传递两个参数BroadcastReceiver
和IntentFilter
//javaLocalBroadcastManager localManager = LocalBroadcastManager.getInstance(mContext);BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "收到广播", Toast.LENGTH_SHORT).show(); }};IntentFilter intentFilter = new IntentFilter("LocalBroadcastManager-test");localManager.registerReceiver(receiver, intentFilter);//注册广播
//kotlinval localManager = LocalBroadcastManager.getInstance(mContext)val broadReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { Toast.makeText(context, "收到广播", Toast.LENGTH_SHORT).show() }}val intentFilter = IntentFilter("LocalBroadcastManager-test")localManager.registerReceiver(broadReceiver, intentFilter)
- 通过本地发送广播
通过上面定义BroadcastReceiver来接收广播处理,现在可以发送广播试试了
//javalocalManager.sendBroadcast(new Intent("LocalBroadcastManager-test"));
//kotlinlocalManager.sendBroadcast(Intent("LocalBroadcastManager-test"))
LocalBroadcastManager 源码分析
LocalBroadcastManager位于android.support.v4.content包下
因为本地广播基于观察者模式设计,所以将LocalBroadcastManager设计成单例,被观察者只有一个嘛,以下是获取实例和私有构造方法
// 忽略部分代码public static LocalBroadcastManager getInstance(@NonNull Context context) { Object var1 = mLock; synchronized(mLock) { if (mInstance == null) { mInstance = new LocalBroadcastManager(context.getApplicationContext()); } return mInstance; }}private LocalBroadcastManager(Context context) { this.mAppContext = context; //UI线程的Looper,说明可以在子线程获取实例、发送广播 this.mHandler = new Handler(context.getMainLooper()) { public void handleMessage(Message msg) { switch(msg.what) { case 1: LocalBroadcastManager.this.executePendingBroadcasts(); break; default: super.handleMessage(msg); } } };}
在LocalBroadcastManager中有两个内部静态类,封装了BroadcastReceiver和IntentFilter
// 忽略部分代码private static final class ReceiverRecord { final IntentFilter filter;//注册广播时的intentFilter final BroadcastReceiver receiver;//注册广播时的broadcastReceiver boolean broadcasting;//是否添加到广播队列 boolean dead;//死亡标识 ReceiverRecord(IntentFilter _filter, BroadcastReceiver _receiver) { this.filter = _filter; this.receiver = _receiver; } public String toString() { StringBuilder builder = new StringBuilder(128); builder.append("Receiver{"); builder.append(this.receiver); builder.append(" filter="); builder.append(this.filter); if (this.dead) { builder.append(" DEAD"); } builder.append("}"); return builder.toString(); }}private static final class BroadcastRecord { final Intent intent;//发送广播的intent final ArrayList<LocalBroadcastManager.ReceiverRecord> receivers;//发送广播intent匹配的receivers BroadcastRecord(Intent _intent, ArrayList<LocalBroadcastManager.ReceiverRecord> _receivers) { this.intent = _intent; this.receivers = _receivers; }}
下面看下注册观察都和解注册的代码
// 保存所有注册BroadcastReceiver的HashMapprivate final HashMap<BroadcastReceiver, ArrayList<LocalBroadcastManager.ReceiverRecord>> mReceivers = new HashMap();//保存所有注册BroadcastReceiver中IntentFilter的actionprivate final HashMap<String, ArrayList<LocalBroadcastManager.ReceiverRecord>> mActions = new HashMap();public void registerReceiver(@NonNull BroadcastReceiver receiver, @NonNull IntentFilter filter) { HashMap var3 = this.mReceivers; synchronized(this.mReceivers) { // 创建一个LocalBroadcastManager.ReceiverRecord对象 LocalBroadcastManager.ReceiverRecord entry = new LocalBroadcastManager.ReceiverRecord(filter, receiver); // 从mReceivers中获取是否存在的LocalBroadcastManager.ReceiverRecord对象 ArrayList<LocalBroadcastManager.ReceiverRecord> filters = (ArrayList)this.mReceivers.get(receiver); if (filters == null) { //如果mReceivers不存在要注册的receiver,则创建一个新的,保存到Mreceivers中 filters = new ArrayList(1); this.mReceivers.put(receiver, filters);//保存receiver对应的LocalBroadcastManager.ReceiverRecord } filters.add(entry); for(int i = 0; i < filter.countActions(); ++i) { // 遍历获取filter中所有的action,保存到mActions中 String action = filter.getAction(i); ArrayList<LocalBroadcastManager.ReceiverRecord> entries = (ArrayList)this.mActions.get(action); if (entries == null) { entries = new ArrayList(1); this.mActions.put(action, entries);//保存action对应的LocalBroadcastManager.ReceiverRecord } entries.add(entry); } }}public void unregisterReceiver(@NonNull BroadcastReceiver receiver) { HashMap var2 = this.mReceivers; synchronized(this.mReceivers) { //mReceivers中移除已注册的receiver ArrayList<LocalBroadcastManager.ReceiverRecord> filters = (ArrayList)this.mReceivers.remove(receiver); if (filters != null) {//移除成功不为null for(int i = filters.size() - 1; i >= 0; --i) { LocalBroadcastManager.ReceiverRecord filter = (LocalBroadcastManager.ReceiverRecord)filters.get(i); filter.dead = true;//死亡标识 for(int j = 0; j < filter.filter.countActions(); ++j) { String action = filter.filter.getAction(j); ArrayList<LocalBroadcastManager.ReceiverRecord> receivers = (ArrayList)this.mActions.get(action); if (receivers != null) { for(int k = receivers.size() - 1; k >= 0; --k) { LocalBroadcastManager.ReceiverRecord rec = (LocalBroadcastManager.ReceiverRecord)receivers.get(k); if (rec.receiver == receiver) { rec.dead = true;//标识死亡 receivers.remove(k);//先移除mAction中action对应List中的 } } if (receivers.size() <= 0) { this.mActions.remove(action);//如果action对应的list为0,移除mAction中的action } } } } } }}
发送广播的逻辑
public boolean sendBroadcast(@NonNull Intent intent) { HashMap var2 = this.mReceivers; synchronized(this.mReceivers) { String action = intent.getAction(); String type = intent.resolveTypeIfNeeded(this.mAppContext.getContentResolver()); Uri data = intent.getData(); String scheme = intent.getScheme(); Set<String> categories = intent.getCategories(); boolean debug = (intent.getFlags() & 8) != 0; if (debug) { Log.v("LocalBroadcastManager", "Resolving type " + type + " scheme " + scheme + " of intent " + intent); }// 获取匹配的action的ReceiverRecord对象 ArrayList<LocalBroadcastManager.ReceiverRecord> entries = (ArrayList)this.mActions.get(intent.getAction()); if (entries != null) { if (debug) { Log.v("LocalBroadcastManager", "Action list: " + entries); } ArrayList<LocalBroadcastManager.ReceiverRecord> receivers = null; int i; //遍历匹配到action的广播 for(i = 0; i < entries.size(); ++i) { LocalBroadcastManager.ReceiverRecord receiver = (LocalBroadcastManager.ReceiverRecord)entries.get(i); if (debug) { Log.v("LocalBroadcastManager", "Matching against filter " + receiver.filter); } if (receiver.broadcasting) { if (debug) { Log.v("LocalBroadcastManager", " Filter's target already added"); } } else { int match = receiver.filter.match(action, type, scheme, data, categories, "LocalBroadcastManager"); if (match >= 0) { if (debug) { Log.v("LocalBroadcastManager", " Filter matched! match=0x" + Integer.toHexString(match)); } if (receivers == null) { receivers = new ArrayList(); } receivers.add(receiver); receiver.broadcasting = true; } else if (debug) { String reason; switch(match) { case -4: reason = "category"; break; case -3: reason = "action"; break; case -2: reason = "data"; break; case -1: reason = "type"; break; default: reason = "unknown reason"; } Log.v("LocalBroadcastManager", " Filter did not match: " + reason); } } } if (receivers != null) { for(i = 0; i < receivers.size(); ++i) { ((LocalBroadcastManager.ReceiverRecord)receivers.get(i)).broadcasting = false; }// 添加到广播队列 this.mPendingBroadcasts.add(new LocalBroadcastManager.BroadcastRecord(intent, receivers)); if (!this.mHandler.hasMessages(1)) { //发送消息 this.mHandler.sendEmptyMessage(1); } return true; } } return false; }}
sendBroadcastSync方法有些不同,可自行查看源码
下面来看下处理广播的逻辑
void executePendingBroadcasts() { while(true) { HashMap var2 = this.mReceivers; LocalBroadcastManager.BroadcastRecord[] brs; synchronized(this.mReceivers) { int N = this.mPendingBroadcasts.size(); if (N <= 0) { return; } brs = new LocalBroadcastManager.BroadcastRecord[N]; this.mPendingBroadcasts.toArray(brs); //转换array this.mPendingBroadcasts.clear();//清空操作 } for(int i = 0; i < brs.length; ++i) { LocalBroadcastManager.BroadcastRecord br = brs[i]; int nbr = br.receivers.size(); // 遍历回调onReceiver方法 for(int j = 0; j < nbr; ++j) { LocalBroadcastManager.ReceiverRecord rec = (LocalBroadcastManager.ReceiverRecord)br.receivers.get(j); if (!rec.dead) {//如果没有dead调用onReceiver方法 rec.receiver.onReceive(this.mAppContext, br.intent); } } } }}
到这里就把整个逻辑分析了,主要逻辑有:
- 在LocalBroadcastManager中通过
registerReceiver
中注册广播,保存到mReceivers
和mActions
中 - 通过
sendBroadcast
中匹配mActions
中的BroadcastReceiver,将匹配到的对象保存到mPendingBroadcasts
中 - 最终调用
executePendingBroadcasts
来发送广播
更多相关文章
- Android读取文件方法总结
- Android中Intent传递对象的两种方法(Serializable,Parcelable)!
- Mac安装android studio后卡在building gradle project info的解
- appium 【已解决】Android,每次启动手机中都会安装Appium setting
- android 图片压缩的几种方法
- Android SqLite中insert()方法解析
- android设备调用usb外置摄像头方法及案例
- Android基础教程之-------Android中两种设置全屏的方法!!!