onSaveInstanceState () и onRestoreInstanceState () - PullRequest
134 голосов
/ 04 ноября 2010

Я пытаюсь сохранить и восстановить состояние Activity, используя методы onSaveInstanceState() и onRestoreInstanceState().

Проблема в том, что он никогда не входит в метод onRestoreInstanceState(). Кто-нибудь может объяснить мне, почему это так?

Ответы [ 12 ]

187 голосов
/ 05 ноября 2010

Обычно вы восстанавливаете свое состояние в onCreate().Можно также восстановить его в onRestoreInstanceState(), но не очень часто.(onRestoreInstanceState() вызывается после onStart(), тогда как onCreate() вызывается до onStart().

. Используйте методы put для сохранения значений в onSaveInstanceState():

protected void onSaveInstanceState(Bundle icicle) {
  super.onSaveInstanceState(icicle);
  icicle.putLong("param", value);
}

Ивосстановить значения в onCreate():

public void onCreate(Bundle icicle) {
  if (icicle != null){
    value = icicle.getLong("param");
  }
}

Вам не нужно сохранять состояния просмотра, поскольку они сохраняются автоматически , вызывая super.onSaveInstanceState (icicle);.

147 голосов
/ 17 июля 2011

onRestoreInstanceState() вызывается только при воссоздании активности после того, как она была убита ОС. Такая ситуация случается, когда:

  • ориентация устройства меняется (ваша деятельность уничтожается и воссоздается)
  • перед вами другое действие, и в какой-то момент ОС убивает ваше действие, чтобы освободить память (например). В следующий раз, когда вы начнете свою деятельность, будет вызван onRestoreInstanceState().

В отличие от этого: если вы находитесь в своей деятельности и нажимаете кнопку Back на устройстве, ваша деятельность завершена () завершена (то есть воспринимается как выход из настольного приложения), и при следующем запуске приложения она запускается. «свежий», то есть без сохраненного состояния, потому что вы намеренно вышли из него при нажатии Back.

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

В целом, как указано в документации для onRestoreInstanceState():

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

Как я читал: нет причины переопределять onRestoreInstanceState(), если только вы не подклассифицируете Activity, и ожидается, что кто-то будет наследовать ваш подкласс.

7 голосов
/ 04 ноября 2010

Состояние, которое вы сохраняете при onSaveInstanceState(), позже доступно при вызове onCreate() метода.Поэтому используйте onCreate (и его параметр Bundle), чтобы восстановить состояние вашей активности.

4 голосов
/ 28 мая 2014

В качестве обходного пути вы можете сохранить пакет с данными, которые вы хотите сохранить, в Намерении, которое вы используете для запуска действия A.

Intent intent = new Intent(this, ActivityA.class);
intent.putExtra("bundle", theBundledData);
startActivity(intent);

Действие A должно было бы передать это действие Б.Вы могли бы получить намерение в методе onCreate в Деятельности B.

Intent intent = getIntent();
Bundle intentBundle;
if (intent != null)
    intentBundle = intent.getBundleExtra("bundle");
// Do something with the data.

Другая идея - создать класс репозитория для хранения состояния активности и сделать так, чтобы каждая ваша деятельность ссылалась на этот класс (возможно, с использованием одноэлементной структуры.) Хотяделать это, вероятно, больше проблем, чем стоит.

3 голосов
/ 14 мая 2014

Я обнаружил, что onSaveInstanceState всегда вызывается, когда другая активность выходит на передний план. И так же на стоп.

Однако onRestoreInstanceState вызывался только тогда, когда также вызывались onCreate и onStart. И onCreate и onStart НЕ всегда вызывались.

Так что кажется, что Android не всегда удаляет информацию о состоянии, даже если действие переходит в фоновый режим. Тем не менее, он вызывает методы жизненного цикла для сохранения состояния просто для безопасности. Таким образом, если состояние не удаляется, то Android не вызывает методы жизненного цикла для восстановления состояния, поскольку они не нужны.

Рисунок 2 описывает это.

3 голосов
/ 24 октября 2012

Главное, что если вы не сохраните в onSaveInstanceState(), то onRestoreInstanceState() не будет вызван.Это основное различие между restoreInstanceState() и onCreate().Убедитесь, что вы действительно что-то храните.Скорее всего это ваша проблема.

2 голосов
/ 27 июня 2012

Я думаю, что эта тема была довольно старой.Я только упомянул другой случай, когда onSaveInstanceState() также будет вызван, когда вы звоните Activity.moveTaskToBack(boolean nonRootActivity).

1 голос
/ 07 декабря 2016

Нет необходимости, чтобы onRestoreInstanceState всегда вызывался после onSaveInstanceState.

Обратите внимание, что: onRestoreInstanceState всегда вызывается, когда действие поворачивается (когда ориентация не обрабатывается) или открывается ваше действие, а затем открывается другоеприложения, чтобы ваш экземпляр активности очищался из памяти операционной системой.

1 голос
/ 13 апреля 2015

Если вы обрабатываете изменения ориентации действия с помощью android:configChanges="orientation|screenSize" и onConfigurationChanged(Configuration newConfig), onRestoreInstanceState() не будет вызываться.

0 голосов
/ 29 июня 2016

Я могу сделать это (извините, это c # не Java, но это не проблема ...):

private int iValue = 1234567890;

function void MyTest()
{
Intent oIntent = new Intent (this, typeof(Camera2Activity));
Bundle oBundle = new Bundle();
oBundle.PutInt("MYVALUE", iValue); //=> 1234567890
oIntent.PutExtras (oBundle);
iRequestCode = 1111;
StartActivityForResult (oIntent, 1111);
}

И В ВАШЕЙ ДЕЯТЕЛЬНОСТИ ДЛЯ РЕЗУЛЬТАТА

private int iValue = 0;

protected override void OnCreate(Bundle bundle)
{
Bundle oBundle =  Intent.Extras;
if (oBundle != null)
{
iValue = oBundle.GetInt("MYVALUE", 0);
//=>1234567890
}
}

private void FinishActivity(bool bResult)
{
Intent oIntent = new Intent();
Bundle oBundle = new Bundle();
oBundle.PutInt("MYVALUE", iValue);//=>1234567890
oIntent.PutExtras(oBundle);
if (bResult)
    {
    SetResult (Result.Ok, oIntent);
    }
else
    SetResult(Result.Canceled, oIntent);
GC.Collect();
Finish();

}

НАКОНЕЦ1007 *

protected override void OnActivityResult(int iRequestCode, Android.App.Result oResultCode, Intent oIntent)
{
base.OnActivityResult (iRequestCode, oResultCode, oIntent);
iValue = oIntent.Extras.GetInt("MYVALUE", -1); //=> 1234567890
}
...