何时注销BroadcastReceiver?在onPause(),onDestroy()或onStop()中?

37

在什么时候应该使用 unregisterReceiver?是在 onPause()onDestroy() 还是 onStop() 中?

注意:我需要服务在后台运行。

更新:

  1. 我得到了一个释放接收器 null 异常。

  2. Activity 泄漏了意图接收器,你是否忘记调用了 unregisterReceiver();

请告诉我是否有什么问题,这是我的代码:

private boolean processedObstacleReceiverStarted;
private boolean mainNotificationReceiverStarted;

protected void onResume() {

    super.onResume();
    try {
        registerReceivers();

    } catch (Exception e) {

        Log.e(MatabbatManager.TAG,
                "MAINActivity: could not register receiver for Matanbbat Action "
                        + e.getMessage());
    }
}

private void registerReceivers() {

    if (!mainNotificationReceiverStarted) {
        mainNotificationReceiver = new MainNotificationReceiver();

        IntentFilter notificationIntent = new IntentFilter();

        notificationIntent
                .addAction(MatabbatManager.MATABAT_LOCATION_ACTION);
        notificationIntent
                .addAction(MatabbatManager.MATABAT_New_DATA_RECEIVED);
        notificationIntent
                .addAction(MatabbatManager.STATUS_NOTIFCATION_ACTION);
        registerReceiver(mainNotificationReceiver, notificationIntent);

        mainNotificationReceiverStarted = true;

    }

    if (!processedObstacleReceiverStarted) {
        processedObstacleReceiver = new ProcessedObstacleReceiver();
        registerReceiver(processedObstacleReceiver, new IntentFilter(
                MatabbatManager.MATABAT_ALARM_LOCATION_ACTION));
        processedObstacleReceiverStarted = true;

    }

}

private void unRegisterReceivers() {

    if (mainNotificationReceiverStarted) {
        unregisterReceiver(mainNotificationReceiver);
        mainNotificationReceiverStarted = false;
    }
    if (processedObstacleReceiverStarted) {
        unregisterReceiver(processedObstacleReceiver);
        processedObstacleReceiverStarted = false;
    }

}


@Override
protected void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();

    try {

        unRegisterReceivers();
        mWakeLock.release();//keep screen on
    } catch (Exception e) {
        Log.e(MatabbatManager.TAG, getClass() + " Releasing receivers-" + e.getMessage());
    }

}

首先,您永远不必调用生命周期方法,如onPause()、onDestroy()或onStop()。 - lithos35
你的应用程序预期行为是什么?上述所有情况都是有效的,这取决于你的使用情况。 - gunar
这是一个明确的答案:注册和注销广播接收器 - Yosidroid
有用的答案 注册和注销广播接收器 - Yosidroid
4个回答

92

这取决于您在哪里注册了接收器。互补方法对应的是

onCreate - onDestroy
onResume - onPause
onStart  - onStop

如果您在第一个中注册了接收器,那么请在其结束方法中注销它。


2
@nAkhmedov,请您能否解释一下? - stinepike
6
如果您支持HoneyComb设备以前的版本,则onPause是在应用程序终止之前保证被调用的最后一个生命周期事件处理程序。如果您只支持Post-HoneyComb设备,则onStop是最后一个保证被调用的处理程序。 永远不要假设onDestroy会被调用,因此,在此生命周期事件之前取消注册接收器。 - w3bshark
3
如果您的进程被终止以回收内存,那么注销接收器无关紧要,因为您的应用程序将从内存中清除(包括您的接收器)。只有当您有一些持久性内容并且必须保证该方法被调用时,才需要担心可杀死的状态。 - Kevin Coppock

10

根据Android文档

你应该实现onStop()方法来释放活动资源,例如网络连接或注销广播接收器。

然后,我会遵循这些步骤(使用@StinePike的比喻):

onResume - onPause
onStart  - onStop

由于Android生命周期,正如@w3bshark所提到的:

在HoneyComb(3.0+)设备中,onStop()是最后一个保证被处理的方法。


因此,您必须在onResume和onPause中注册和取消注册接收器,因为它们肯定会在片段或活动被销毁之前调用。 - Pedro Varela

2
如果您想在活动不可见时仍要监听事件,则只需在onStop()中调用unregister()即可。例如,从Activity A打开Activity B,但如果您希望A仍然监听事件,则需要这样做。
但是,如果您只想在活动可见时监听事件,则应在onPause()中调用unregister()。例如,从Activity A打开Activity B,但现在您不想在A中监听事件。
希望这能解决您的问题。

当我们从活动A调用活动B时,活动A将进入onStop状态,接收器将被注销并且不会再监听广播。 - Bawa

1
一个广播接收器是一个不可见的组件。它只是通过onReceive()回调响应某种变化。
因此,在您的活动处于响应状态或正在启用/激活状态(即调用onResume()时)时才激活它们是有意义的。
因此,最好的做法是在onResume()中注册——当活动可见且启用时,并在onStop()中取消注册,当活动不再处于活动状态时。

这通常不起作用,因为从A -> B移动时,活动B的onStart/onResume发生在活动A的onStop之前。错误的活动可能会捕获您的广播,导致难以调试的问题。 - Brian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接