Подтвердить что ты не робот

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

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

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

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

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

@Override 
onRetainNonConfigurationInstance() { 
  mIsChangeConfig = true; 
}
4b9b3361

Ответ 1

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

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

Ответ 3

У меня есть обходное решение для случаев, когда что-то 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);
    }
}

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