Android: Исключено исключение IntentReceiver, хотя я вызываю unregisterReceiver

Я не понимаю, почему я получаю это исключение, когда нажимаю кнопку "Назад". У меня есть IntentReceiver, зарегистрированный в методе onCreate, и он должен быть незарегистрирован в методе onPause. Мой вызов Log.w() внутри метода onPause приводит меня к мысли, что вызывается метод unregisterReceiver(), но я все еще получаю это исключение.

Любые мысли?

private PlayerReceiver playerReceiver;

public void onCreate(Bundle savedInstanceState) {
 ...
     IntentFilter playerFilter;     
     playerReceiver = new PlayerReceiver();
     playerFilter = new IntentFilter(PlayerService.BUFFERING_FAILURE);
     playerFilter.addAction(PlayerService.BUFFERING_SUCCESS);
     registerReceiver(playerReceiver, playerFilter);
 ...
}

protected void onPause() {
 ...
     if (playerReceiver != null){
         unregisterReceiver(playerReceiver);
         Log.w(TAG, "playerReceiver has been unregistered");
         playerReceiver = null;
     }
 ...
}

public class PlayerReceiver extends BroadcastReceiver {

    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(PlayerService.BUFFERING_FAILURE)){
            setListenButton(false);
        }
        closePlayDialog();
    }
}

Выход LogCat

08-26 11:44:28.646: WARN/WWOZMain(1058): playerReceiver has been unregistered    
08-26 11:44:29.476: ERROR/ActivityThread(1058): Activity org.wwoz.WWOZMain has leaked IntentReceiver o[email protected] that was originally registered here. Are you missing a call to unregisterReceiver()?    
08-26 11:44:29.476: ERROR/ActivityThread(1058): android.app.IntentReceiverLeaked: Activity org.wwoz.WWOZMain has leaked IntentReceiver [email protected] that was original
Здесь зарегистрирован

. Вам не хватает вызова unregisterReceiver()?

Ответ 1

Это проблема жизненного цикла Android-активности. Я вижу это в основном действии, а затем тестирую на устройстве с помощью кнопки "Назад", которая возвращается к экрану заставки.

В методе onPause().

Отмените регистрацию BroadcastReceiver, которую вы создали в onCreate()

В onRestart() перерегистрируйте новый широковещательный приемник.

В классе активности вам необходимо сохранить запись широковещательного приемника как члена данных экземпляра.

ВТОРОЕ

Я думаю, что это также проблема с улучшением функции с Android.

Иногда разработчику нужен вещательный приемник, чтобы пережить активность. Например, чтобы понять, когда доступны определенные состояния экрана или нет. Подумайте о контексте беседы модели рабочего потока, которая имеет много состояний.

ТРЕТИЙ

Вы можете зарегистрировать и отменить регистрацию широковещательных приемников с активностью, но простой вызов типа isRegistered(BroadcastReceiver) в классе Activity может оказаться очень полезным.

Если вам нужны приемники, чтобы выжить за пределами активности, я не отвечаю, кроме как заставить замолчать предупреждение, добавив unregister(X) в вызов onDestroy(). YMMV; -)

Ответ 2

У меня была такая же проблема. Причиной было то, что я случайно зарегистрировал один и тот же BroadcastReceiver дважды.

Ответ 3

Моя ситуация была похожа на Mullins, я зарегистрировал приемник как в классе, так и в его подклассе.

Для новичков, подобных мне, просто переключите точку останова на receiver, а затем отлаживайте приложение. Если ресивер похож на [email protected], тогда как журнал ошибок в logcat отличается от него, например [email protected], с символами после "@", вы наверняка зарегистрировали его дважды (или более).

(Выше нравится комментарий под ответом Маллинса, на самом деле, я публикую его здесь, потому что я не могу оставлять комментарии сейчас.)