源码阅读--BroadcastReceiver广播机制

注册Receiver

BroadcastReceiver有两种:动态Receiver和静态Receiver(8.0开始已经禁止对隐式广播注册静态Receiver了,隐式广播是指非该app独有的广播),划分依据是注册时机的不同;
在Manifest文件中注册的Receiver是静态Receiver,在安装应用的时候解析安装包,会把相应的解析信息保存在PackageManagerService;
动态Receiver是在应用用户代码中使用Context对象的registerReceiver方法注册。

数据结构

AMS有两个Receiver相关的成员:mRegisteredReceivers和mReceiverResolver;

mRegisteredReceivers

mRegisteredReceivers从命名就可以看出这个是用于保存动态注册的Receiver的数据结构。这是一个HashMap,具体的类型是HashMap< IBinder, ReceiverList>;IBinder是客户端应用对应的一个Binder对象,ReceiverList继承自ArrayList。
这里写图片描述
BroadcastFilter是IntentFilter的子类,好吧,貌似跟BroadcastReceiver没有什么关系???

回顾一下AMS对Activity的管理,每一个Activity组件对应AMS服务端的一个ActivityRecord对象,在客户端应用中ActivityThread中有一个mActivities成员ArrayMap< IBinder, ActivityClientRecord >,每一个ActivityClientRecord对应着一个Activity,也就是ActivityRecord和ActivityClientRecord存在着一一对应关系。客户端应用、AMS服务端和WMS使用token来统一标示一个Activity,这个token是ActivityRecord的appToken。
这里写图片描述
这是一个IApplicationToken.Stub对象,IApplicationToken是一个AIDL接口,appToken是一个IBinder对象。
看似有一些类似的地方,ActivityThread的mActivities是一个Map,键值是一个Binder对象,保存了所有的Activity对应的ActivityClientRecord;AMS的mRegisteredReceivers也是一个Map,键值是一个Binder对象。
这里的Binder是什么? 查看AMS的registerReceiver方法可以知道这是一个IIntentReceiver。
在客户端应用注册Receiver时,也有IIntentReceiver

这里写图片描述
应用每个BroadcastReceiver对应一个ReceiverDispatcher,每个ReceiverDispatcher包含一个IIntentReceiver.Stub对象,每个IIntentReceiver.Stub在AMS中对应mRegisteredReceivers中的一个键,ok,BroadcastReceiver和mRegisteredReceivers中的每个键值对也有了一一对应关系。
回想一下静态Receiver的配置,一个receiver是可以对应多个IntentFilter的,所以键值对的值部分是一个BroadcastFilter列表。

mReceiverResolver

mReceiverResolver是一个IntentResolver类型对象,保存了所有的注册了的BroadcastFilter,在收到广播后会根据广播Intent过滤得到符合要求的Filter(queryIntent);但是怎么对应到Receiver呢?
我们知道mRegisteredReceivers每个键值对对应一个Receiver,值的不分是一个ReceiverList(BroadcastFilter列表),在BroadcastFilter中保存了其所属的ReceiverList引用,ReceiverList又保存了对应的Binder键值的引用,这样我们就可以根据BroadcastFilter找到对应的Receiver了。
总结一下,类结构图

这里写图片描述

注册流程

1.既然涉及到AMS肯定少不了Binder通信机制,在客户端应用,一般动态注册的Receiver是通过在Activity中调用registerReceiver,Activity并没有重写该方法,实现是在ContextImpl类中。
2.在客户端与AMS通信之前,App会对BroadcastReceiver进行封装得到一个ReceiverDispatcher对象(为了一个能够唯一标示的Binder对象?)
3.通过Binder机制远程调用AMS的registerReceiver方法。创建BroadcastFilter对象添加到相应数据结构,处理粘性广播。

发送广播

数据结构

广播的发送相关的数据结构主要是由BroadcastQueue实现。这个类包含两个列表对象mParallelBroadcasts,mOrderedBroadcasts分别作为普通广播和有序广播的处理队列。

广播流程

1.ContextImpl类sendBroadcast方法触发AMS的broadcastIntent方法。
2.broadcastIntentLocked处理,安全检查(判断保护类广播,广播是否来自系统应用);处理package相关广播;处理sticky广播,保存Intent;收集匹配Receiver,包括静态和动态,创建BroadcastRecord对象,入队BroadcastQueue并调度处理。
3.BroadcastQueue调用processNextBroadcast处理。触发普通广播处理;处理有序广播:动态广播直接触发,静态广播判断是否跳过,注册Receiver应用是否已启动,未启动需先启动应用进程
4.超时处理:broadcastTimeoutLocked AppNotResponding
这里写图片描述

猜你喜欢

转载自blog.csdn.net/yuanjw2014/article/details/78775232