为什么我的Activity泄漏了?

Jas*_*ing 2 android broadcastreceiver android-lifecycle android-activity

我有一个具有IntentFilter和BroadcastReceiver的Activity,我将它们注册到我的onCreate().

IntentFilter filter = new IntentFilter(ACTION_RCV_MESSAGE);
filter.addCategory(Intent.CATEGORY_DEFAULT);
receiver = new MessageReceiver();
registerReceiver(receiver, filter);
Run Code Online (Sandbox Code Playgroud)

但在结束我的应用程序时,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);
}
Run Code Online (Sandbox Code Playgroud)

当我打电话时,为什么我的活动仍在泄露unregisterReceiver()

Dar*_*tle 5

根据活动生命周期,您的应用程序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);
}
Run Code Online (Sandbox Code Playgroud)

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

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

最后,请注意我使用您的代码是为了简单.在现实中,你可能会想设置您的IntentFilter并在的messageReceiver onCreate(),然后只需调用registerReceiver()onResume().

更新:一个更重要的说明.根据实现生命周期回调:

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

这里的许多人在super.onWhatever()方法结束时而不是在开始时显示呼叫.