在Android开发中,我们经常需要注册BroadcastReceiver和bind service。
接口函数如下:
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter);
public void unregisterReceiver(BroadcastReceiver receiver);
public boolean bindService(Intent service, ServiceConnection conn, int flags);
public void unbindService(ServiceConnection conn);
有的时候,用户只调用了注册函数,或者是bind service,而忘记了unregisterReceiver和unbindService。这时,在Activity退出的时候,会自动这些问题,自动调用unregisterReceiver和unbindService。具体的流程如下:
private void handleDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
ActivityClientRecord r = performDestroyActivity(token, finishing,
configChanges, getNonConfigInstance); 回调Activity的onDestroy
if (r != null) {
// Mocked out contexts won’t be participating in the normal
// process lifecycle, but if we’re running with a proper
// ApplicationContext we need to have it tear down things
// cleanly.
Context c = r.activity.getBaseContext();
if (c instanceof ContextImpl) {
((ContextImpl) c).scheduleFinalCleanup(
r.activity.getClass().getName(), “Activity”); 清理 注册的receiver和bind的service
}
}
if (finishing) {
try {
ActivityManagerNative.getDefault().activityDestroyed(token); 通知AMS,activity已经destroy
} catch (RemoteException ex) {
// If the system process has died, it’s game over for everyone.
}
}
mSomeActivitiesChanged = true;
}
In ContextImpl.java
final void scheduleFinalCleanup(String who, String what) {
mMainThread.scheduleContextCleanup(this, who, what);
}
In ActivityThread.java
final void scheduleContextCleanup(ContextImpl context, String who,
String what) {
ContextCleanupInfo cci = new ContextCleanupInfo();
cci.context = context;
cci.who = who;
cci.what = what;
sendMessage(H.CLEAN_UP_CONTEXT, cci);
}
case CLEAN_UP_CONTEXT:
ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
cci.context.performFinalCleanup(cci.who, cci.what);
break;
In ContextImpl.java
final void performFinalCleanup(String who, String what) {
//Log.i(TAG, “Cleanup up context: ” + this);
mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
}
In LoadedApk.java
public void removeContextRegistrations(Context context,
String who, String what) {
final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap = mReceivers.remove(context);
if (rmap != null) {
for (int i=0; i<rmap.size(); i++) { 清理所有已经注册的receiver
LoadedApk.ReceiverDispatcher rd = rmap.valueAt(i);
IntentReceiverLeaked leak = new IntentReceiverLeaked(
what + ” ” + who + ” has leaked IntentReceiver “
+ rd.getIntentReceiver() + ” that was ” +
“originally registered here. Are you missing a ” +
“call to unregisterReceiver()?”);
leak.setStackTrace(rd.getLocation().getStackTrace());
Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
if (reportRegistrationLeaks) {
StrictMode.onIntentReceiverLeaked(leak);
}
try {
ActivityManagerNative.getDefault().unregisterReceiver(
rd.getIIntentReceiver());
} catch (RemoteException e) {
// system crashed, nothing we can do
}
}
}
mUnregisteredReceivers.remove(context);
//Slog.i(TAG, “Receiver registrations: ” + mReceivers);
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap =
mServices.remove(context);
if (smap != null) {
for (int i=0; i<smap.size(); i++) { 解绑定已经bind的service
LoadedApk.ServiceDispatcher sd = smap.valueAt(i);
ServiceConnectionLeaked leak = new ServiceConnectionLeaked(
what + ” ” + who + ” has leaked ServiceConnection “
+ sd.getServiceConnection() + ” that was originally bound here”);
leak.setStackTrace(sd.getLocation().getStackTrace());
Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
if (reportRegistrationLeaks) {
StrictMode.onServiceConnectionLeaked(leak);
}
try {
ActivityManagerNative.getDefault().unbindService(
sd.getIServiceConnection());
} catch (RemoteException e) {
// system crashed, nothing we can do
}
sd.doForget();
}
}
mUnboundServices.remove(context);
//Slog.i(TAG, “Service registrations: ” + mServices);
}