Когда отменить регистрацию BroadcastReceiver? В onPause(), onDestroy() или onStop()?

Когда я должен использовать unregisterReceiver? В onPause(), onDestroy() или onStop()?

Примечание. Мне нужно, чтобы служба работала в фоновом режиме.

Обновлять:

  1. Я получаю исключение, освобождающее приемники null.

  2. Активность просочилась в приемники намерений, вы пропустили вызов 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());
    }

}

person Muhammad    schedule 15.01.2014    source источник
comment
Во-первых, вам никогда не придется вызывать методы жизненного цикла, такие как onPause(), onDestroy() или onStop().   -  person lithos35    schedule 15.01.2014
comment
Каково ожидаемое поведение вашего приложения? Все вышеперечисленные случаи действительны, все зависит от вашего варианта использования.   -  person gunar    schedule 15.01.2014
comment


Ответы (4)


это зависит от того, где вы зарегистрировали приемник. Дополнительные пары методов:

onCreate - onDestroy
onResume - onPause
onStart  - onStop

если вы зарегистрируете приемник в первом, то отмените его регистрацию в методе окончания.

person stinepike    schedule 15.01.2014
comment
@nAkhmedov, объясни пожалуйста - person stinepike; 08.06.2015
comment
Последний обработчик событий жизненного цикла, который гарантированно будет вызван перед завершением работы приложения (если вы поддерживаете устройства до HoneyComb), — onPause. Если вы поддерживаете только устройства Post-HoneyComb, то onStop является последним гарантированным обработчиком. Вы никогда не должны предполагать, что onDestroy будет вызываться, и поэтому вы должны отменить регистрацию получателя до этого события жизненного цикла. Источник: документы для разработчиков Android - person w3bshark; 04.11.2015
comment
@ w3bshark: если ваш процесс уничтожается для освобождения памяти, то не имеет значения, отмените ли вы регистрацию получателя, так как ваше приложение будет удалено из памяти (включая ваш получатель). Вам нужно беспокоиться о уничтожаемых состояниях только в том случае, если у вас есть что-то постоянное, и вы должны гарантировать, что метод будет вызван. - person Kevin Coppock; 18.02.2016

Из документации Android:

Вы должны реализовать onStop() для освобождения ресурсов активности, таких как сетевое соединение, или для отмены регистрации широковещательных приемников.

Затем я бы следовал этим парам (используя аналогию @StinePike):

onResume - onPause
onStart  - onStop

Из-за жизненного цикла Android и, как отметил @w3bshark:

В устройствах после HoneyComb (3.0+) onStop() является последним гарантированным обработчиком.

person Evin1_    schedule 18.02.2016
comment
Таким образом, вы должны регистрировать и отменять регистрацию получателей в onResume и onPause, потому что они будут вызываться наверняка до того, как фрагмент или активность будут уничтожены. - person Pedro Varela; 21.04.2016

Это так же просто, если вы хотите прослушивать события, даже если ваша активность не видна, тогда вызовите отмену регистрации в onStop() (например, из Activity A вы открываете Activity B, но если вы хотите, чтобы A все еще прослушивал события) .

Но если вы хотите прослушивать только события, когда ваша активность видна, тогда в onPause вызовите unregister() (например, из Activity A вы открыли Activity B, но теперь вы не хотите прослушивать события в Activity A).

Надеюсь, это поможет вашей проблеме.

person Sudhanshu Gaur    schedule 03.08.2017
comment
когда мы вызываем действие A для действия B, действие A переходит в состояние onStop, а получатель отменяет регистрацию и не будет слушать трансляции. - person Bawa; 23.10.2019

Широковещательный приемник является невидимым компонентом. Все, что он делает, это отвечает на какое-то изменение с помощью обратного вызова onReceive().

Поэтому имеет смысл активировать их только тогда, когда ваша активность находится в состоянии ответа или когда она становится включенной/активной, то есть когда вызывается onResume().

Поэтому лучше зарегистрироваться в onResume() — когда активность видна и включена, и отменить регистрацию в onStop(), когда активность больше не активна.

person WonderBoy    schedule 24.06.2014
comment
Часто это не сработает, так как onStart/onResume действия B происходит раньше, чем onStop действия A (при переходе из A -> B). Неправильная активность может перехватить вашу трансляцию, что вызовет проблемы с отладкой. - person Brian; 02.11.2015