我们动态注册一个广播,一般是这么写:
BroadcastReceiver receiver=..;
IntentFilter filter=...;
MainActivity.this.registerReceiver(receiver,filter);
registerReceiver()具体实现在ContextImpl类中:
ContextImpl.java
#1
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
#2
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, filter, broadcastPermission,
scheduler, getOuterContext());
}
#3
private Intent registerReceiverInternal(BroadcastReceiver receiver,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver(); //关键点别漏了哦
}
}
try { //上面代码构建了一个rd,并保存。
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(),
rd, filter, broadcastPermission); //filter实现了Parcelable接口
} catch (RemoteException e) {
return null;
}
}
上面干了些啥?
创建一个ReceiverDispatcher,获取内部的InnerReceiver,作为参数通过binder调用ams的注册方法
下面看看AMS.registerReceiver()方法:
AMS.java p9977
public Intent registerReceiver(IApplicationThread caller,
IIntentReceiver receiver, IntentFilter filter, String permission)
{
synchronized(this) {
ProcessRecord callerApp = null;
if (caller != null) { //根据传入的caller找到ProcessRecord
callerApp = getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when registering receiver " + receiver);
}
}
List allSticky = null;
// Look for any matching sticky broadcasts...
Iterator actions = filter.actionsIterator(); //IntentFilter上设置的action们
if (actions != null) {
while (actions.hasNext()) {
String action = (String)actions.next();
allSticky = getStickiesLocked(action, filter, allSticky);
}
} else {
allSticky = getStickiesLocked(null, filter, allSticky);
}
// The first sticky in the list is returned directly back to
// the client.
Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;
if (DEBUG_BROADCAST) Slog.v(TAG, "Register receiver " + filter
+ ": " + sticky);
if (receiver == null) {
return sticky;
}
ReceiverList rl //根据binder key找到ReceiverList value
= (ReceiverList)mRegisteredReceivers.get(receiver.asBinder()); //IIntentReceiver 类型
if (rl == null) {
rl = new ReceiverList(this, callerApp,
Binder.getCallingPid(),
Binder.getCallingUid(), receiver); //IIntentReceiver 类型,实现了binder哦
if (rl.app != null) { //app即为callerApp ,ProcessRecord 记录一个进程?
rl.app.receivers.add(rl); //rl间接保存在ProcessRecord里面
} else {
try {
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
mRegisteredReceivers.put(receiver.asBinder(), rl); //rl保存在ams里,key为binder
}
BroadcastFilter bf = new BroadcastFilter(filter, rl, permission);
rl.add(bf);
if (!bf.debugCheck()) {
Slog.w(TAG, "==> For Dynamic broadast");
}
mReceiverResolver.addFilter(bf);
// Enqueue broadcasts for all existing stickies that match
// this filter. 这里和粘性广播有关,略过吧,分析主线即可
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);
BroadcastRecord r = new BroadcastRecord(intent, null,
null, -1, -1, null, receivers, null, 0, null, null,
false, true, true);
if (mParallelBroadcasts.size() == 0) {
scheduleBroadcastsLocked();
}
mParallelBroadcasts.add(r);
}
}
return sticky;
}
}
上面这段代码干了以下这些事:
构建一个ReceiverList ,里面有对应于应用进程的ProcessRecord类型的callerApp,IItentReceiver类型的receiver(实现了binder,来自binder另一端)
然后,app.receivers.add(rl),也就是callerApp间接持有上面创建的rl,换种说法,ProcessRecord间接持有一个BroadcastFilter 类型的List列表
同时, mRegisteredReceivers.put(receiver.asBinder(), rl),rl保存在ams里,rl是List的子类哦
另外,创建一个BroadcastFilter ,里面有filter, rl, permission,并且, rl.add(bf),这里说明一下,ReceiverList 继承了ArrayLists,泛型参数是BroadcastFilter
最后, mReceiverResolver.addFilter(bf);暂时不明白上面意思。
上面只分析了典型的动态注册广播的过程,主要是为了让我们对广播的注册过程有个整体上的认识,至于细节部分,没必要都搞清楚,否则很容易走偏主线,打乱思路,不利分析,毕竟源码分析本竟是一个很枯燥的过程,
ps:这篇文章一开始是写在有道云笔记上的,所以没有怎么排版,而且我在对照源码分析时可能会删掉些无关紧要的代码,所以大家在分析时一定要自己对照源码,只有自己对照源码,自己尝试分析,才能真正的理解,进步,这个我深有体会。好的,这篇文章虽然写的不是很好,看还是希望对大家有帮助!!本人的写作水平实在不敢恭维,尤其是技术文章,见笑了,不过我会慢慢学习,加强写作和表达能力的。另外,文章可能有理解错误的地方,请谅解。。