ContextImpl#registerReceiverInternal(...)
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {//一般都会进入这里
//...
rd = mPackageInfo.getReceiverDispatcher(//mPackageInfo是LoadedApk
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);//然后进入这里
} else {
//...
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
} catch (RemoteException e) {
return null;
}
}
LoadedApk#getReceiverDispatcher(...)
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
LoadedApk.ReceiverDispatcher rd = null;
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
if (registered) {
map = mReceivers.get(context);//每个ContextImpl中都保存了一个Map
if (map != null) {
rd = map.get(r);//如果这个broadcastReceiver已经注册过,就不加入map中
}
}
if (rd == null) {//如果这个Receiver没有注册过,则创建一个ReceiverDispatcher实例
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
if (registered) {
if (map == null) {
map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
mReceivers.put(context, map);
}
map.put(r, rd);//加入该应用进程堆的Map中
}
} else {
rd.validate(context, handler);//查看是否使用不同的Context注册同一个Receiver
}
rd.mForgotten = false;
return rd.getIIntentReceiver();
}
}
根据实验和分析源码,其实反复注册同一个BroadcastReceiver实例并不会造成更多的内存泄露。如果一个Activity周期中注册了Receiver,而Activity生命周期结束时,没有注销该Receiver,在onDestroy中,会去LoadedApk中把Activity的注册的BroadcastReceiver及相关的对象销毁,在该Activity中bindService的service也会unbind。所以其实这种泄露比较小。同一个Broadcast Receiver使用不同的Context注册时,会相当于多次注册,和创建多个IIntentReceiver。如果使用同一Context对同一个Receiver对象注册,在应用中不会新增任何对象,只是如果使用的IntentFilter没有注册过,则在AMS中新增一个BroadcastFilter对象。