为什么我的Activity泄漏了?

时间:2012-07-03 04:26:31

标签: android broadcastreceiver android-activity android-lifecycle

我有一个具有IntentFilter和BroadcastReceiver的Activity,我在onCreate()中注册它们。

IntentFilter filter = new IntentFilter(ACTION_RCV_MESSAGE);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new MessageReceiver();
registerReceiver(receiver, filter);

但在结束我的应用程序时,Logcat说:

  

07-03 01:38:19.567:ERROR / ActivityThread(304):android.app.IntentReceiverLeaked:Activity com.intentservicetest5.IntentServiceTest5Activity泄露了最初在这里注册的IntentReceiver com.intentservicetest5.IntentServiceTest5Activity$MessageReceiver@44efe8a8。你是否错过了对unregisterReceiver()的调用?

但我确实有

public void onDestroy(Bundle savedInstanceState){
    unregisterReceiver(receiver);
}

为什么在拨打unregisterReceiver()时,我的活动仍在泄露?

4 个答案:

答案 0 :(得分:5)

根据Activity Lifecycle,您的应用在onPause()之后的任何时间都可以在大多数设备(任何低于Android 3.0 / API级别12的设备)上以及onStop()之后的任何时间播放任何设备。这意味着无法保证调用onDestroy()。然后,“活动”中注册和取消注册广播的最佳位置分别为onResume()onPause()

@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);
}

请注意,正如@VipalShah指出的那样,您使用了onDestroy()的错误签名。这就是为什么没有调用unregisterReceiver()的原因。使用@Override将帮助您解决此类问题。

另请注意,onPause()onResume()之间的对称是有意的。如果您查看上面链接的活动生命周期文章,您会看到在初始启动期间调用onResume(),而不仅仅是从暂停时恢复。所以你只需要在这里注册广播,而不是onCreate()

最后,请注意我使用您的代码是为了简单。实际上,您可能希望在onCreate()中设置IntentFilter和MessageReceiver,然后只需在registerReceiver()中调用onResume()

更新:还有一个重要提示。根据{{​​3}}:

  

在执行任何工作之前,您对这些生命周期方法的实现必须始终调用超类实现。

这里有很多人在方法结束时而不是在开头时显示对super.onWhatever()的调用。

答案 1 :(得分:1)

当应用程序退出时,并不总能保证

onDestroy 被调用。您应该尝试取消注册 onStop onPause

另外,请确保在覆盖的方法中调用Activity的超类方法:

@Override
public void onPause() {
    unregisterReceiver(receiver);
    super.onPause();
}

答案 2 :(得分:0)

    @Override
        protected void onPause() {
            super.onPause();
            unregisterReceiver(receiver);
        }   

onPause()

中试用

答案 3 :(得分:0)

尝试使用此onDestroy()

@Override
protected void onDestroy() {

    unregisterReceiver(receiver);

    super.onDestroy();
}