Когда именно вызываются onSaveInstanceState () и onRestoreInstanceState ()?

102

На следующем рисунке (из официального документа ) описывается хорошо известный жизненный цикл активности Android:

введите описание изображения здесь

С другой стороны, когда действие уничтожается системой (например, из-за того, что необходимо освободить память), состояние действия иногда автоматически сохраняется и восстанавливается с помощью методов onSaveInstanceState()и onRestoreInstanceState(), как показано на следующем рисунке (также из официального документа ):

введите описание изображения здесь

Я знаю, что onSaveInstanceState()это не всегда вызывается, когда активность вот-вот будет уничтожена. Например, если он уничтожен, потому что пользователь нажал кнопку «назад», состояние активности не сохраняется. Но в тех случаях , когда состояние будет сохранено и восстановлено, и onSaveInstanceState()/ onRestoreInstanceState()дозвонились, когда именно они называются ?

Например, согласно приведенным выше рисункам, onRestoreInstanceState()может вызываться до onStart()или после, onStart()но до onResume()или после onResume(). Точно так же существует несколько возможностей для onSaveInstanceState(). Так когда именно они называются?

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

Луис Мендо
источник
получил окончательный ответ из официального документа Android, onSaveInstanceState (), вызываемого между onPause () и onStop ().
Риши
1
@Rishi Не могли бы вы дать ссылку на этот документ?
Луис Мендо,
прочтите пункт «Сохранить состояние вашей активности»
Риши,
прав я или нет, пожалуйста, поясните
Риши

Ответы:

107

Согласно документации :

void onRestoreInstanceState (Bundle savedInstanceState)

Этот метод вызывается между onStart()и onPostCreate(Bundle).

void onSaveInstanceState (связать outState)

Если вызывается, этот метод будет выполняться после onStop () для приложений, ориентированных на платформы, начиная с Build.VERSION_CODES.P. Для приложений, ориентированных на более ранние версии платформы, этот метод будет выполняться перед onStop (), и нет никаких гарантий относительно того, произойдет ли он до или после onPause ().

Стив М
источник
1
Спасибо. Не могли бы вы дать ссылки на документацию?
Луис Мендо
Итак, я также не думаю, что есть что-то еще между onStart () и onPostCreate (), поэтому onRestoreInstanceState () хорошо определен в цепочке.
Steve M
Большое спасибо. Это проясняет проблему
Луис Мендо
1
@SteveM «Нет никаких гарантий относительно того, произойдет ли это до или после onPause ()» Означает ли это, что если мы попытаемся получить доступ к представлению (чтобы получить какое-то значение для сохранения, например, индекс из представления списка), мы можем столкнуться с NullPointerExceptions?
Tiago
3
Затем, что рекомендуется: сохранить структуру данных в onPause и восстановить ее в onResume, а не в onSaveInstanceState и onRestoreInstanceState?
Gödel77 08
19

Согласно doc1 и doc2

onSaveInstanceState

До Honeycomb действия не считались уничтожаемыми до тех пор, пока они не были приостановлены, что означало, что onSaveInstanceState () вызывалась непосредственно перед onPause (). Однако, начиная с Honeycomb, Activity считаются убиваемыми только после того, как они были остановлены, а это означает, что onSaveInstanceState () теперь будет вызываться перед onStop (), а не непосредственно перед onPause ().

onRestoreInstanceState

Этот метод вызывается между onStart () и onPostCreate (Bundle), когда действие повторно инициализируется из ранее сохраненного состояния.

Разработчик Android
источник
понравилось, как вы описали сценарии в разных версиях Android
Джимит Патель,
14

В дополнение к уже опубликованным ответам в Android P внесено небольшое изменение, а именно:

void onSaveInstanceState (связать outState)

Если вызывается этот метод будет происходить ПОСЛЕ onStop() для приложений , ориентированных на платформы , начиная с P . Для приложений, ориентированных на более ранние версии платформы, этот метод будет выполняться раньше, onStop()и нет никаких гарантий относительно того, произойдет ли это до или после onPause().

Источник: документы

Относительно того, почему вводится это изменение, вот ответ:

... так что приложение может безопасно выполнять транзакции фрагментов onStop()и иметь возможность сохранять постоянное состояние позже.

Источник: документы

азизбекский
источник
Привет, отличный комментарий. Вы знаете, как будет вести себя приложение, которое нацелено на P, но работает на более низком api? То же, что и приложение с таргетингом на более низкий api, или оно будет согласованным для api и сохранит поведение «targeting api»?
Filipkowicz 05
@Filipkowicz, Do you know how will behave app that target P but runs on lower api?пока приложение работает, скажем, на M, версия Android, которая есть на этом устройстве, не содержит изменений, представленных в P, что означает, что независимо от того, что вы указали цель, Pвы не увидите отличается для устройств pre-P. Надеюсь, что это ответ на ваш вопрос.
azizbekian 07
Я чувствую себя так расслабленно сегодня после прочтения этого ответа, потому что я проходил бесплатный курс Android на Udacity, и у них все еще есть старая версия руководств, в которой в уроке 5, упражнение 8 говорится, что методы onStop и onDestroy не должны присутствовать в отображаемый textView. Но я не знал, что это было для более старых версий Android, и я запускал свое приложение на Android-пироге и получал метод onStop в моем textView. Огромное спасибо. Наконец-то чувствую себя хорошо.
Санду
6

Это дополнительная информация для onSaveInstanceState (Bundle)

из документов

Не путайте этот метод с обратными вызовами жизненного цикла активности, такими как onPause (), который всегда вызывается, когда действие помещается в фоновый режим или на пути к уничтожению, или onStop (), который вызывается перед уничтожением. Один из примеров того, когда вызываются onPause () и onStop (), а не этот метод, - это когда пользователь переходит от действия B к действию A: нет необходимости вызывать onSaveInstanceState (Bundle) на B, потому что этот конкретный экземпляр никогда не будет восстановлен , поэтому система избегает его вызова. Пример, когда вызывается onPause (), а не onSaveInstanceState (Bundle), - это когда действие B запускается перед действием A: система может избежать вызова onSaveInstanceState (Bundle) для действия A, если оно не было убито в течение времени жизни B, поскольку состояние пользовательского интерфейса A останется неизменным.

Так что это реализация по умолчанию для ..

Реализация по умолчанию заботится о большей части состояния пользовательского интерфейса для каждого экземпляра, вызывая onSaveInstanceState () для каждого представления в иерархии, имеющего идентификатор, и сохраняя идентификатор текущего сфокусированного представления (все из которых восстанавливаются реализация по умолчанию onRestoreInstanceState (Bundle)). Если вы переопределите этот метод, чтобы сохранить дополнительную информацию, не захваченную каждым отдельным представлением, вы, вероятно, захотите обратиться к реализации по умолчанию, в противном случае будьте готовы сохранить все состояние каждого представления самостоятельно.

Махмуд Мзз
источник
0
String activityState;
@Override 
public void onCreate(Bundle savedInstanceState) {
// call the super class onCreate to complete the creation of activity like 
// the view hierarchy 
super.onCreate(savedInstanceState);

// recovering the instance state 
if (savedInstanceState != null) {
     activityState = savedInstanceState.getString(STATE_KEY);
 } 

   setContentView(R.layout.main_activity);
   mTextView = (TextView) findViewById(R.id.text_view);
} 

// Этот обратный вызов вызывается только в том случае, если есть сохраненный экземпляр, ранее сохраненный с помощью // onSaveInstanceState (). Мы восстанавливаем какое-то состояние в onCreate (), в то время как мы можем при желании восстановить // другое состояние здесь, возможно, используемое после завершения onStart (). // Пакет savedInstanceState такой же, как тот, который используется в onCreate ().

@Override 
public void onRestoreInstanceState(Bundle savedInstanceState) {
 mTextView.setText(savedInstanceState.getString(STATE_KEY));
  } 


// invoked when the activity may be temporarily destroyed, save the instance 
//state here 
//this method will be called before onstop

@Override 
 public void onSaveInstanceState(Bundle outState) {
    outState.putString(STATE_KEY, activityState);

    // call superclass to save any view hierarchy 
    super.onSaveInstanceState(outState);
} 
Парвез Рафи
источник
Простите, как это отвечает на вопрос, когда именно вызываются методы сохранения / восстановления ?
Луис Мендо