问题
I have an Activity that has an IntentFilter and a BroadcastReceiver, and I register them in my onCreate()
.
IntentFilter filter = new IntentFilter(ACTION_RCV_MESSAGE);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new MessageReceiver();
registerReceiver(receiver, filter);
But upon ending my app, Logcat says:
07-03 01:38:19.567: ERROR/ActivityThread(304): android.app.IntentReceiverLeaked: Activity com.intentservicetest5.IntentServiceTest5Activity has leaked IntentReceiver com.intentservicetest5.IntentServiceTest5Activity$MessageReceiver@44efe8a8 that was originally registered here. Are you missing a call to unregisterReceiver()?
But I do have
public void onDestroy(Bundle savedInstanceState){
unregisterReceiver(receiver);
}
Why is my Activity still leaking when I do call unregisterReceiver()
?
回答1:
Per the Activity Lifecycle, your app is killable any time after onPause()
on most devices (any device with less than Android 3.0 / API level 12), and any time after onStop()
on any device. That means onDestroy()
is not guaranteed to be called. The best place in an Activity to register and unregister for broadcasts, then, is onResume()
and onPause()
, respectively:
@Override
protected void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter(ACTION_RCV_MESSAGE);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new MessageReceiver();
registerReceiver(receiver, filter);
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
Note that as @VipalShah pointed out, you were using the wrong signature for onDestroy()
. This is why unregisterReceiver()
wasn't being called. Using @Override
will help you catch this kind of problem.
Also note that the symmetry between onPause()
and onResume()
is intentional. If you look at the Activity lifecycle article linked to above, you'll see that onResume()
is called during the initial start-up, not just when resuming from pause. So you only need to register for the broadcast here, not in onCreate()
.
Finally, note that I used your code for simplicity. In reality, you'll probably want to set up your IntentFilter and MessageReceiver in onCreate()
, and then just call registerReceiver()
in onResume()
.
Update: One more important note. As per Implementing the lifecycle callbacks:
Your implementation of these lifecycle methods must always call the superclass implementation before doing any work.
Many people here were showing the call to super.onWhatever()
at the end of the method rather than at the beginning.
回答2:
onDestroy is not always guaranteed to be called when an application exits. You should try unregistering it onStop or onPause.
Also, make sure you call your Activity's super class methods in your overridden methods:
@Override
public void onPause() {
unregisterReceiver(receiver);
super.onPause();
}
回答3:
Try to use this onDestroy()
@Override
protected void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}
回答4:
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
Try it in onPause()
来源:https://stackoverflow.com/questions/11304450/why-does-my-activity-leak