【问题标题】:When to unregister BroadcastReceiver? In onPause(), onDestroy(), or onStop()?何时注销 BroadcastReceiver?在 onPause()、onDestroy() 还是 onStop() 中?
【发布时间】:2014-02-03 20:46:14
【问题描述】:

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

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

更新:

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

  2. Activity 已泄露 Intent 接收器,您是否错过了对 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());
    }

}

【问题讨论】:

标签: android broadcastreceiver intentservice


【解决方案1】:

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

onCreate - onDestroy
onResume - onPause
onStart  - onStop

如果您在第一个中注册接收器,然后在其结束方法中取消注册。

【讨论】:

  • @nAkhmedov,你能解释一下吗
  • 保证在应用程序终止之前调用的最后一个生命周期事件处理程序(如果您支持 HoneyComb 之前的设备)是 onPause。如果您只支持 Post-HoneyComb 设备,那么 onStop 是最后一个有保证的处理程序。你永远不应该假设 onDestroy 会被调用,因此你应该在这个生命周期事件之前取消注册接收器。来源:Android Developer docs
  • @w3bshark:如果您的进程被杀死以回收内存,那么您是否取消注册接收器并不重要,因为您的应用程序将从内存中逐出(包括您的接收器)。如果你有一些持久的东西,你只需要担心可终止的状态,并且你必须保证该方法会被调用。
【解决方案2】:

来自Android documentation

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

然后,我会遵循这些对(使用@StinePike 的类比):

onResume - onPause
onStart  - onStop

因为Android Lifecycle,以及@w3bshark 提到的:

在后 HoneyComb (3.0+) 设备中,onStop() 是最后保证的处理程序。

【讨论】:

  • 因此,您必须在 onResume 和 onPause 中注册和取消注册接收器,因为它们会在 Fragment 或 Activity 销毁之前被确定调用。
【解决方案3】:

就这么简单,如果您想在活动不可见的情况下监听事件,请在 onStop() 中调用 unregister (例如,从 Activity A 中打开 Activity B,但如果您希望 A 仍然监听事件)。

但是,当您只想在活动可见时仅侦听事件时,请在 onPause 中调用 unregister() (例如,您从 Activity A 打开了 Activity B,但现在您不想监听 Activity A 中的事件)。

希望这对您的问题有所帮助。

【讨论】:

  • 当我们调用activity A 到activity B 时,activity A 进入onStop 状态并且receiver 将被取消注册并且不会监听广播。
【解决方案4】:

广播接收器是一个不可见的组件。它所做的一切都是通过 onReceive() 回调响应某种变化。

所以激活它们才有意义,只有当您的活动处于响应状态或变为启用/活动时 - 即调用 onResume() 时。

因此,最好在 onResume() 中注册 - 当活动可见且已启用时,当活动不再处于活动状态时,在 onStop() 中取消注册。

【讨论】:

  • 这通常不起作用,因为活动 B 的 onStart/onResume 发生在活动 A 的 onStop 之前(从 A -> B 移动时)。错误的活动可能会捕获您的广播,从而导致难以调试的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-24
  • 1970-01-01
相关资源
最近更新 更多