该系列文章总纲链接:专题总纲目录 Android Framework 总纲
本章关键点总结 & 说明:
说明:本章节主要解读广播组件的动态注册/注销过程及静态注册过程。关注思维导图中左上侧部分即可。
有了前面startActivity流程和service组件启动流程分析的基础,基于此,接下来我们来分析广播组件的注册/注销/发送广播流程。
我们先对广播组件的整体设计思路有一个了解,再详细分析其接收器注册/注销关键流程。
1 注册/注销/广播发送设计思路解读
1.1 设计思路概要解读
广播组件的分析和之前会有一些不同,主要是对关键流程的理解,以及一些成员变量的设计意义和目的,当然这些本章后面都会讲到。在解读这些关键流程前,我们从设计师的视角先来俯瞰下Android广播组件的几个关键流程,大概的设计思路整理如下:
- 注册流程:注册receiver时,和AMS进行通信,将要注册的receiver和filter按照一定规则放入到AMS的一个表X中,方便查找和删除。
- 注销流程:注销receiver时,和AMS进行通信,找到对应的表X,从中将receiver从表X中删除。
- 广播发送流程:A进程 发送广播时,和AMS进行通信,查找表中是否有对应的recevier,如果存在就找到当时注册receiver的进程B,调用B中对应的recevier中的onReceiver方法。
1.2 设计思路详细解读
基于此,我们对这几个流程进行展开说明,进行更详细的解读,具体如下:
@1 注册流程:
- 应用层操作:应用通过
Context
对象(如Activity
或Service
)调用registerReceiver()
方法来注册一个BroadcastReceiver
。 - 构建IntentFilter:应用传入一个
IntentFilter
对象,该对象定义了BroadcastReceiver
感兴趣的广播类型(如特定动作、数据类型等)。 - 与AMS通信:应用层的注册请求会通过Binder IPC(进程间通信)传递给
ActivityManagerService
(AMS),AMS是Android系统中负责管理应用生命周期和广播的守护进程。 - 存储映射关系:AMS会将
BroadcastReceiver
与IntentFilter
的映射关系存储在一个内部的数据结构中,通常是哈希表或类似的数据结构。 - 返回Receiver对象:AMS返回一个
IIntentReceiver
对象(Binder代理),用于后续的注销操作。
@2 注销流程:
- 应用层操作:应用调用
unregisterReceiver()
方法,并传入之前注册的BroadcastReceiver
实例。 - 与AMS通信:应用层的注销请求同样通过Binder IPC传递给AMS。
- 查找映射关系:AMS根据传入的
BroadcastReceiver
实例查找之前存储的映射关系。 - 删除映射关系:如果找到对应的映射关系,AMS会将其从内部数据结构中删除,从而注销
BroadcastReceiver
。 - 确认注销:注销操作完成后,AMS会向应用层确认注销成功。
@3 广播发送流程:
- 发送广播:当一个应用、系统组件或其他进程需要发送广播时,它会通过
Context
或sendBroadcast()
方法发送广播。 - 与AMS通信:发送请求同样通过Binder IPC传递给AMS。
- 查找匹配的Receiver:AMS会根据广播的
Intent
(包含动作、数据等信息)查找内部数据结构中匹配的IntentFilter
。 - 匹配Receiver:AMS会检查哪些注册的
BroadcastReceiver
对当前广播感兴趣(即IntentFilter
匹配)。 - 跨进程调用:对于匹配的
BroadcastReceiver
,AMS会通过Binder代理调用其onReceive()
方法。如果BroadcastReceiver
位于不同的进程,AMS会负责进程间的通信。 - 执行Receiver:
BroadcastReceiver
的onReceive()
方法被调用,执行相应的逻辑。
注意:在广播发送流程中,AMS不仅仅是查找表中的BroadcastReceiver
,还需要检查这些BroadcastReceiver
的权限和安全性,确保只有合适的接收者能够接收到特定的广播。此外,广播的发送和接收过程还涉及到广播的优先级、发送方式(如有序广播或普通广播)等因素。但这些都不是设计的主干,因此我们可以暂时忽略。
本章节,我们主要关注注册/注销广播接收器的流程。
2 注册/注销广播接收器代码流程解读
2.1 AMS.registerReceiver动态注册流程解读
准备一个IIntentReceiver对象,调用AMS的registerReceiver方法。代码实现如下:
//AMS
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
// 确保调用者不是隔离的进程
enforceNotIsolatedCaller("registerReceiver");
// 获取调用者的UID和PID
int callingUid;
int callingPid;
synchronized(this) {
ProcessRecord callerApp = null;
if (caller != null) {
// 如果caller非空,则获取其对应的ProcessRecord
callerApp = getRecordForAppLocked(caller);
// ...
callingUid = callerApp.info.uid;
callingPid = callerApp.pid;
} else {
// 如果caller为空,则使用Binder框架获取调用者的包名、UID和PID
callerPackage = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
}
// 处理传入的用户ID
userId = this.handleIncomingUser(callingPid, callingUid, userId,
true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
// 查找匹配的粘性广播
// 初始化一个列表,用于存储找到的粘性广播
List allSticky = null;
// 获取IntentFilter的action迭代器
Iterator actions = filter.actionsIterator();
if (actions != null) {
// 如果存在action,则遍历每一个action
while (actions.hasNext()) {
String action = (String)actions.next();
// 对于每个action,尝试获取匹配该action的粘性广播
// getStickiesLocked方法会根据action和IntentFilter来查找粘性广播
allSticky = getStickiesLocked(action, filter, allSticky, UserHandle.USER_ALL);
// 再次查找,这次是针对发送广播的调用者的用户ID
allSticky = getStickiesLocked(action, filter, allSticky, UserHandle.getUserId(callingUid));
}
} else {
// 如果没有特定的action,说明广播接收器对所有动作都感兴趣
// 首先尝试获取针对所有用户的粘性广播
allSticky = getStickiesLocked(null, filter, allSticky, UserHandle.USER_ALL);
// 然后尝试获取针对调用者用户ID的粘性广播
allSticky = getStickiesLocked(null, filter, allSticky, UserHandle.getUserId(callingUid));
}
// 如果有匹配的粘性广播,则取出第一个Intent
Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
if (receiver == null) {
return sticky;
}
// 获取或创建ReceiverList对象
//这里出现了一个关键成员变量:mRegisteredReceivers
ReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
// 如果ReceiverList中的app字段(即ProcessRecord)不为null,
// 说明这个接收器属于一个应用进程,那么将ReceiverList添加到该进程的接收器列表中。
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
// 如果app为null,说明这个接收器不属于任何应用进程(可能是一个隐藏的API使用情况或者是系统服务),
// 那么需要将ReceiverList与receiver的Binder对象关联起来,以便在接收器进程死亡时能够收到通知。
try {
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
// 将新创建的ReceiverList对象放入mRegisteredReceivers映射中,以便将来能够找到并管理这个接收器。
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
//...
// 创建BroadcastFilter对象并添加到ReceiverList和mReceiverResolver中
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,permission, callingUid, userId);
rl.add(bf);
//这里出现了另一个关键成员变量:mReceiverResolver
mReceiverResolver.addFilter(bf);
// 如果有匹配的粘性广播,则将它们分发给新的接收器,需要立即调度广播并发送
if (allSticky != null) {
ArrayList receivers = new ArrayList();
receivers.add(bf);
int N = allSticky.size();
// 遍历列表中的每一个粘性广播
for (int i=0; i<N; i++) {
Intent intent = (Intent)allSticky.get(i);
// 为当前的Intent找到对应的BroadcastQueue。BroadcastQueue是广播分发的队列,它根据Intent的属性(如用户ID)来确定
BroadcastQueue queue = broadcastQueueForIntent(intent);
// 创建一个新的BroadcastRecord对象,它代表了即将被分发的广播。BroadcastRecord包含了广播的所有相关信息,如:
/* queue:广播队列。
* intent:广播的Intent。
* receivers:接收器列表,这里只包含了新注册的接收器。
* AppOpsManager.OP_NONE:应用操作码,这里使用OP_NONE表示没有特定的操作。
* 其他参数根据需要进行设置,有些参数在这里设置为null或特定的值。
*/
BroadcastRecord r = new BroadcastRecord(queue, intent, null,
null, -1, -1, null, null, AppOpsManager.OP_NONE, receivers, null, 0,
null, null, false, true, true, -1);
// 将新的BroadcastRecord加入到BroadcastQueue中。这个方法会在广播队列的锁定状态下将广播加入队列,以便稍后处理。
queue.enqueueParallelBroadcastLocked(r);
// 在广播队列的锁定状态下检查并处理队列中的广播,确保它们按照正确的顺序和时机被分发。
queue.scheduleBroadcastsLocked();
}
}
// 返回匹配的粘性广播
return sticky;
}
}
我们可以将这段代码分成以下几个阶段来理解,分别解读如下:
@1 权限和调用者验证及用户ID处理阶段
- 确保调用者不是隔离的进程:通过
enforceNotIsolatedCaller
方法确保调用registerReceiver
的进程不是隔离进程。 - 获取调用者的UID和PID:根据传入的
IApplicationThread
(caller)和String
(callerPackage),获取调用者的ProcessRecord
,进而获取UID和PID。如果caller
为null
,则通过Binder框架直接获取。 - 处理传入的用户ID:通过
handleIncomingUser
方法处理传入的用户ID,确保操作在正确的用户上下文中进行。
@2 粘性广播查找阶段
- 查找匹配的粘性广播:遍历
IntentFilter
中的动作,查找与这些动作匹配的粘性广播。粘性广播是一种特殊的广播,它可以被保存并在BroadcastReceiver
注册后立即发送给它。
@3 广播接收器注册阶段:关键变量mRegisteredReceivers相关操作
- 获取或创建ReceiverList对象:通过
mRegisteredReceivers
(一个关键成员变量)获取与receiver
关联的ReceiverList
,如果不存在则创建一个新的ReceiverList
。 - 关联Binder死亡通知:如果
ReceiverList
中的app
字段为null
,则将ReceiverList
与receiver
的Binder对象关联起来,以便在接收器进程死亡时能够收到通知。
@4 广播过滤器创建和关联:关键变量mReceiverResolver相关操作
- 创建BroadcastFilter对象:创建一个新的
BroadcastFilter
对象,它包含了IntentFilter
、ReceiverList
、权限等信息。 - 添加到ReceiverList和mReceiverResolver:将
BroadcastFilter
添加到ReceiverList
和mReceiverResolver
中。mReceiverResolver
是另一个关键成员变量,它用于存储和解析广播过滤器。
@5 粘性广播分发阶段
- 分发粘性广播:如果有匹配的粘性广播,创建
BroadcastRecord
并将其加入到对应的BroadcastQueue
中,以便稍后处理。 - 返回匹配的粘性广播:返回找到的第一个匹配的粘性广播,如果没有则返回
null
。
整体来看,这段代码处理了从验证调用者权限、查找粘性广播、注册广播接收器、创建广播过滤器到分发粘性广播的完整流程。这些步骤确保了BroadcastReceiver
能够正确注册,并且能够接收到它感兴趣的广播。
2.2 AMS.unregisterReceiver动态注销流程解读
调用AMS的unregisterReceiver方法。代码实现如下:
//AMS
public void unregisterReceiver(IIntentReceiver receiver) {
final long origId = Binder.clearCallingIdentity();
try {
boolean doTrim = false; // 标记是否需要修剪应用程序工作集
synchronized(this) {
// 从mRegisteredReceivers映射中获取与传入receiver关联的ReceiverList对象
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl != null) {
// 如果当前ReceiverList有正在处理的广播
if (rl.curBroadcast != null) {
// 获取当前正在处理的广播记录
BroadcastRecord r = rl.curBroadcast;
// 完成当前接收器的广播处理,并返回是否需要处理下一个广播
final boolean doNext = finishReceiverLocked(
receiver.asBinder(), r.resultCode, r.resultData,
r.resultExtras, r.resultAbort);
// 如果需要处理下一个广播
if (doNext) {
doTrim = true; // 设置标记为true
// 处理下一个广播
r.queue.processNextBroadcast(false);
}
}
// 如果ReceiverList关联了应用进程
if (rl.app != null) {
// 从应用进程的接收器列表中移除当前ReceiverList
rl.app.receivers.remove(rl);
}
// 从mRegisteredReceivers映射中移除ReceiverList
removeReceiverLocked(rl);
// 如果ReceiverList关联了Binder死亡通知
if (rl.linkedToDeath) {
rl.linkedToDeath = false;
rl.receiver.asBinder().unlinkToDeath(rl, 0);
}
}
}
// 如果完成了广播处理,可能需要修剪应用程序工作集
if (doTrim) {
trimApplications();
return;
}
} finally {
// 恢复调用者的身份信息
Binder.restoreCallingIdentity(origId);
}
}
这段代码的关键逻辑包括:
- 广播处理完成:如果
ReceiverList
中还有正在处理的广播,会调用finishReceiverLocked
方法来完成当前接收器的广播处理,并根据返回值决定是否需要处理下一个广播。 - 移除ReceiverList:从
mRegisteredReceivers
映射中移除对应的ReceiverList
对象,这意味着该接收器不再接收任何广播。 - 取消Binder死亡通知:如果
ReceiverList
关联了Binder死亡通知,需要取消这个关联,以防止在接收器进程死亡时AMS接收到不必要的通知。 - 修剪应用程序工作集:如果完成了广播处理,可能需要调用
trimApplications
方法来修剪应用程序工作集,释放一些资源。
其中removeReceiverLocked的功能实现,即从系统中移除一个ReceiverList对象的具体实现如下:
//AMS
void removeReceiverLocked(ReceiverList rl) {
// 从mRegisteredReceivers映射中移除与rl关联的Binder对象
mRegisteredReceivers.remove(rl.receiver.asBinder());
// 获取ReceiverList中的BroadcastFilter数量
int N = rl.size();
// 遍历ReceiverList中的每个BroadcastFilter
for (int i = 0; i < N; i++) {
// 从mReceiverResolver中移除每个BroadcastFilter
mReceiverResolver.removeFilter(rl.get(i));
}
}
这段代码的关键点在于:
- 移除Binder引用:从
mRegisteredReceivers
映射中移除与ReceiverList
关联的Binder引用,这意味着该ReceiverList
不再被AMS跟踪和管理。 - 遍历BroadcastFilter:遍历
ReceiverList
中的每个BroadcastFilter
对象,这些对象代表了与ReceiverList
关联的广播过滤器。 - 移除BroadcastFilter:从
mReceiverResolver
中移除每个BroadcastFilter
对象,mReceiverResolver
是AMS中用于解析和分发广播的关键组件。
这个方法确保了一个ReceiverList
及其关联的所有BroadcastFilter
从AMS中被彻底移除,这是广播接收器注销流程中的重要一步。
总之,整个过程就是将对应的receiver安全地删除掉。
2.3 静态注册receiver流程解读
静态 receiver 是android应用在 AndroidManifest.xml 文件中声明的 receiver,像这样:
<receiver
android:name=".YourBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="your.action.YOUR_ACTION" />
</intent-filter>
</receiver>
它们的信息会在系统启动时,由PMS解析并记录下来。当 AMS 调用 PMS 的接口来查询 “和 intent 匹配的组件” 时,PMS 内部就会去查询当初记录下来的数据,并把结果返回 AMS。
这里PMS在初始化时其中一部分是通过scanDirLI相关方法来初始化成员变量mReceivers的,关于PMS的初始化部分内容,想有更多了解可参考文章:
Android Framework 包管理子系统(01)PackageManagerService启动分析
这里主要看以scanDirLI为入口,分析mReceivers的初始化部分逻辑,代码实现如下所示:
//PMS
//关键流程:step1
private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
final File[] files = dir.listFiles();
//...
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
if (!isPackage) {
// Ignore entries which are not packages
continue;
}
try {
scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
scanFlags, currentTime, null);
} catch (PackageManagerException e) {
//...
}
}
}
//关键流程:step2
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
long currentTime, UserHandle user) throws PackageManagerException {
//...
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags
| SCAN_UPDATE_SIGNATURE, currentTime, user);
//...
return scannedPkg;
}
//关键流程:step3
private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags,
int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
boolean success = false;
try {
final PackageParser.Package res = scanPackageDirtyLI(pkg, parseFlags, scanFlags,
currentTime, user);
success = true;
return res;
} finally {
//...
}
}
//关键流程:step4
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,
int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
//...
synchronized (mPackages) {
//...
int N = pkg.receivers.size(); // 获取应用包中广播接收器的数量
StringBuilder r = null; // 用于存储接收器名称的StringBuilder
for (int i = 0; i < N; i++) { // 遍历应用包中的所有广播接收器
// 获取广播接收器的Activity对象
PackageParser.Activity a = pkg.receivers.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName, pkg.applicationInfo.uid);
// 将广播接收器添加到mReceivers中
mReceivers.addActivity(a, "receiver");
// 如果设置了PARSE_CHATTY标志,记录广播接收器的名称
if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}
//...
}
//...
//返回处理后的应用包对象
return pkg;
}
对于静态注册的解析,实际上到此就结束了。当发送广播时会通过PMS的queryIntentReceivers方法来查询可以处理给定Intent的广播接收器(BroadcastReceiver)。接下来我们来查看该方法的实现,代码如下:
//PMS
@Override
public List<ResolveInfo> queryIntentReceivers(Intent intent, String resolvedType, int flags,
int userId) {
// 检查用户是否存在,如果不存在返回空列表
if (!sUserManager.exists(userId)) return Collections.emptyList();
// 获取Intent中指定的组件名称
ComponentName comp = intent.getComponent();
// 如果Intent中没有指定组件,尝试从Selector中获取
if (comp == null) {
if (intent.getSelector() != null) {
intent = intent.getSelector();
comp = intent.getComponent();
}
}
// 如果Intent中指定了组件
if (comp != null) {
// 创建一个ResolveInfo列表,最多包含一个元素
List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
// 获取对应组件的ActivityInfo
ActivityInfo ai = getReceiverInfo(comp, flags, userId);
// 如果找到了对应的ActivityInfo
if (ai != null) {
// 创建一个ResolveInfo对象,并填充ActivityInfo
ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
// 将ResolveInfo添加到列表中
list.add(ri);
}
// 返回ResolveInfo列表
return list;
}
// 如果Intent中没有指定组件,使用mReceivers进行查询
synchronized (mPackages) {
// 获取Intent中指定的包名
String pkgName = intent.getPackage();
// 如果Intent中没有指定包名
if (pkgName == null) {
// 使用mReceivers查询所有匹配的广播接收器
return mReceivers.queryIntent(intent, resolvedType, flags, userId);
}
// 如果Intent中指定了包名
final PackageParser.Package pkg = mPackages.get(pkgName);
// 如果找到了对应的Package
if (pkg != null) {
// 使用mReceivers查询指定包中匹配的广播接收器
return mReceivers.queryIntentForPackage(intent, resolvedType, flags, pkg.receivers,userId);
}
// 如果没有找到对应的Package,返回null
return null;
}
}
queryIntentReceivers
方法是PKMS中用于查询可以处理特定Intent的广播接收器的关键方法。它支持通过组件名称、包名或全局查询来找到匹配的广播接收器,并返回它们的ResolveInfo
列表。
总体来说,静态接收器注册后,信息是放在PMS中的,而当发送广播时,会通过PMS的receiver查询方法queryIntentReceivers方法来获取对应的接收器相关信息。
3 注册/注销的关键表解读
针对广播组件的所谓注册表,我们主要关注2个关键的成员变量:mRegisteredReceivers和mReceiverResolver。接下来对其进行重点详细解读。
3.1 mRegisteredReceivers解读
mRegisteredReceivers是Android系统中ActivityManagerService(AMS)的一个关键成员变量,其设计目的和意义主要体现在以下几个方面:
- 记录已注册的广播接收器:
mRegisteredReceivers
用于记录所有已经被注册给广播的IIntentReceiver
。它作为一个HashMap,以IIntentReceiver
的Binder代理对象为键,以ReceiverList
对象为值,存储了所有动态注册的广播接收器的信息。 - 快速查找和分发广播:当有广播发送时,AMS需要能够快速找到所有匹配的广播接收器。
mRegisteredReceivers
使得AMS能够根据接收器的Binder代理对象快速定位到对应的ReceiverList
,进而将广播分发给正确的接收器。 - 管理多个广播接收器:一个应用可能注册了多个广播接收器,
mRegisteredReceivers
通过ReceiverList
来管理这些接收器。ReceiverList
表示一个注册了一个或多个广播的receiver,这样当收到广播时,AMS可以根据传入的receiver在mRegisteredReceivers
快速找到对应的ReceiverList
。 - 进程管理和生命周期关联:
ReceiverList
中包含了与特定BroadcastReceiver
关联的进程信息(如ProcessRecord
),这使得当广播需要被分发时,系统能够知道该广播接收器所在的进程状态,以及是否需要启动进程来处理广播。 - Binder死亡通知:如果
ReceiverList
中的app
字段为null
,说明这个接收器不属于任何应用进程,那么需要将ReceiverList
与receiver的Binder对象关联起来,以便在接收器进程死亡时能够收到通知。 - 动态注册与注销:
mRegisteredReceivers
在动态注册和注销BroadcastReceiver
时起到了关键作用。在注册时,它保存了ReceiverList
以便将来匹配和分发广播;在注销时,它会移除对应的ReceiverList
,确保不再向已注销的接收器分发广播。
可以看出,mRegisteredReceivers
的设计目的是为了高效地管理动态注册的广播接收器,确保广播可以准确地分发到正确的接收器,并且能够处理接收器的生命周期事件。这种设计使得Android的广播机制更加灵活和高效。
3.2 mReceiverResolver解读
mReceiverResolver
在Android系统中的设计目的是为了高效地解析和分发广播。它是一个IntentResolver
对象,专门用来处理广播意图(Intent)的解析工作。以下是mReceiverResolver
的主要作用和设计意义:
- 解析Intent:
mReceiverResolver
负责解析传入的广播Intent,根据Intent中的动作(Action)、数据(Data)、类型(Type)等信息,找到与之匹配的BroadcastReceiver
。这是通过维护一个BroadcastFilter
列表来实现的,每个BroadcastFilter
都包含了一个IntentFilter
,用于匹配特定的Intent。 - 维护BroadcastFilter列表:
mReceiverResolver
中保存了所有动态注册的广播接收器对应的BroadcastFilter
。当应用调用registerReceiver
方法时,会创建一个BroadcastFilter
对象,并将其添加到mReceiverResolver
中。 - 快速匹配:在广播发送时,
mReceiverResolver
可以根据Intent快速匹配到对应的BroadcastFilter
,进而找到对应的ReceiverList
,这个列表中包含了所有对该Intent感兴趣的BroadcastReceiver
。 - 广播分发:找到匹配的
BroadcastFilter
后,mReceiverResolver
会将广播分发给对应的BroadcastReceiver
。这个过程是广播发送流程中的关键步骤,确保了正确的接收器能够接收到正确的广播。 - 动态注册与注销:
mReceiverResolver
在动态注册和注销BroadcastReceiver
时也起到了关键作用。在注册时,它保存了BroadcastFilter
以便将来匹配和分发广播;在注销时,它会移除对应的BroadcastFilter
,确保不再向已注销的接收器分发广播。
可以看出,mReceiverResolver
是Android系统中广播机制的核心组件之一,它通过维护一个BroadcastFilter
列表来实现对广播Intent的快速解析和分发,从而保证了广播机制的高效性和准确性。