Как отличить, вызвана ли onDestroy () как часть последовательности изменения конфигурации?

18

В моей деятельности в onDestroy () необходимо уничтожить какую-то внешнюю вещь (услугу). Но я не хочу этого, когда происходит изменение конфигурации (например, переключение клавиатуры), потому что он будет восстановлен сразу.

Итак, вопрос заключается в следующем: как отличить, вызвано ли onDestroy () нажатием клавиши Back-key или частью процесса изменения конфигурации?

после ответа @ CommonsWare было бы довольно просто) что-то вроде:

@Override 
onDestroy() { 
  if (mIsChangeConfig == true) { 
    mIsChangeConfig = false: 
  } else { 
    stopService(); 
  } 
} 

@Override 
onRetainNonConfigurationInstance() { 
  mIsChangeConfig = true; 
}
    
задан Mix 16.07.2011 в 12:58
источник
  • показать код. По крайней мере, псевдокод. Это не дает достаточно информации. –  Andrew Anderson 16.07.2011 в 13:00
  • добавлен псевдокод к вопросу ... –  Mix 17.07.2011 в 22:59

3 ответа

24

В Android 3.x (уровень API 11) вы можете вызвать isChangingConfigurations() , чтобы узнать, уничтожена ли активность из-за изменения конфигурации.

До этого переопределите onRetainNonConfigurationInstance() и установите элемент данных boolean (например, isChangingConfigurations ) на true и проверьте, что член данных в onDestroy() .

    
ответ дан CommonsWare 16.07.2011 в 14:04
  • Спасибо, у меня появилась идея ... единственная уловка - как очистить этот флаг, но надеюсь, что я это выясню) –  Mix 17.07.2011 в 22:50
  • Кроме того, при использовании библиотеки поддержки FragmentActivity (android.support.v4.app.FragmentActivity) на pre-Honeycomb, onRetainNonConfigurationInstance () объявляется окончательным, но вы можете переопределить onRetainCustomNonConfigurationInstance () вместо того же эффекта. (Это немного неочевидно, потому что устаревший тег приводит вас к совершенно другому API, который нельзя использовать таким образом.) –  benkc 16.01.2013 в 21:57
  • Если я правильно понимаю документацию, то isChangingConfigurations () доступен уже в onStop (), но onRetainNonConfigurationInstance () вызывается между onStop () и onDestroy (), если вообще. Таким образом, эти варианты, к сожалению, не совсем эквивалентны. –  Kaarel 19.01.2013 в 00:25
  • @CommonsWare В чем разница между использованием isChangingConfigurations () и isFinishing ()? –  android developer 28.03.2014 в 14:05
  • @CommonsWare Да, я так и думал, но я не могу придумать никакого конца. –  android developer 28.03.2014 в 14:38
Показать остальные комментарии
6

Это может сделать трюк для вас (от Как отличить изменение ориентации и оставить андроид приложения ):

  

Использовать метод isFinishing () Activity.

Пример кода:

@Override
protected void onDestroy() {
  super.onDestroy();

  if (isFinishing()) {
    // Do stuff
  } else { 
    // It's an orientation change.
  }
}
    
ответ дан German Latorre 27.03.2014 в 17:16
  • Это также возможно. Интересно, но какая разница между его использованием и «isChangingConfigurations» (кроме того, что они противоположны друг другу). –  android developer 28.03.2014 в 14:04
  • ! isFinishing () подразумевает либо изменение ориентации, либо переход в заднюю часть. –  Kevin Krumwiede 03.09.2014 в 01:18
  • лучше называть isFinishing in onPause, поскольку onDestroy не всегда может вызываться в соответствии с документами на developer.android.com/reference/android/app/...: Примечание: не считайте, что этот метод называется местом для сохранение данных! –  morgwai 08.02.2017 в 18:56
0

У меня есть обходное решение для случаев, когда что-то X нужно делать на onStop (), но вы не хотите, чтобы это было сделано, если есть изменение конфигурации (и, очевидно, у вас нет доступных isChangingConfigurations () ).

Техника заключается в выполнении этого действия X на AsyncTask и отсрочке. Вы вызываете AsyncTask в onStop () / onPause (), а в onRetainCustomNonConfigurationInstance () вы отменяете задачу. Таким образом, если пользователь нажимает домашний ключ, например, код X будет выполняться на фоне. Однако, если есть поворот экрана, X-код не будет выполнен, потому что задача будет отменена до ее выполнения (это значение задержки).

Я использую его, например, для решения проблем с wakelocks: освобождая их onPause (), но не если пользователь меняет ориентацию экрана.

Вот мой код:

private class ReleaseWakeLockDelayedTask extends AsyncTask<WakeLock, Integer, Integer>{

    @Override
    protected Integer doInBackground(WakeLock... params) {

        try {
            // Delay so that onRetainCustomNonConfigurationInstance is in
            //  time of cancelling the task
            Thread.sleep(5000);  
        } catch (InterruptedException e) {}

        if(isCancelled()) return null;
        releaseWakeLock(params[0]); // own method that calls the actual release
        return null;
    }
}


@Override
public Object onRetainCustomNonConfigurationInstance() {
    ...
    if(mReleaseWakeLockTask != null && mReleaseWakeLockTask .getStatus() != AsyncTask.Status.FINISHED){
        mReleaseWakeLockTask.cancel(true));
    }
    ...
}

@Override
protected void onPause() {
    // create and call the task
    boolean wRun;

    if(mReleaseWakeLockTask != null){
        if(mReleaseWakeLockTask .getStatus() != AsyncTask.Status.FINISHED) wRun= false;
        else wRun= true;
    }else wRun = true;

    if(wRun){
        mReleaseWakeLockTask = new mReleaseWakeLockTask ();
        mReleaseWakeLockTask .execute(wakeLock);
    }
}

Надеюсь, что это поможет!

    
ответ дан Pek Ifly 11.04.2013 в 02:58