Пытаюсь сохранить и восстановить состояние с Activity
помощью методов onSaveInstanceState()
и onRestoreInstanceState()
.
Проблема в том, что он никогда не входит в onRestoreInstanceState()
метод. Может кто-нибудь объяснить мне, почему это так?
Пытаюсь сохранить и восстановить состояние с Activity
помощью методов onSaveInstanceState()
и onRestoreInstanceState()
.
Проблема в том, что он никогда не входит в onRestoreInstanceState()
метод. Может кто-нибудь объяснить мне, почему это так?
Ответы:
Обычно вы восстанавливаете свое состояние в 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");
}
}
onRestoreInstanceState()
вызывается только при воссоздании активности после того, как она была убита ОС. Такая ситуация бывает, когда:
В отличие от этого: если вы находитесь в своей деятельности и Back
нажимаете кнопку на устройстве, ваша деятельность будет завершена (т.е. думать об этом как о выходе из настольного приложения), и в следующий раз, когда вы запустите свое приложение, оно будет запущено «заново», т.е. сохраненное состояние, потому что вы намеренно вышли из него при ударе Back
.
Другой источник путаницы заключается в том, что когда приложение теряет фокус на другое приложение, onSaveInstanceState()
вызывается, но когда вы переходите обратно к вашему приложению, он onRestoreInstanceState()
может не вызываться. Это случай, описанный в исходном вопросе, т.е. если ваша активность НЕ была убита в период, когда другая активность была впереди onRestoreInstanceState()
, НЕ будет вызываться, потому что ваша активность в значительной степени «живая».
В целом, как указано в документации для onRestoreInstanceState()
:
Большинство реализаций просто используют onCreate (Bundle) для восстановления своего состояния, но иногда бывает удобно сделать это здесь после того, как вся инициализация была выполнена, или чтобы позволить подклассам решать, использовать ли вашу реализацию по умолчанию. Реализация этого метода по умолчанию выполняет восстановление любого состояния представления, которое ранее было заморожено onSaveInstanceState (Bundle).
Насколько я читал: нет причин переопределять, onRestoreInstanceState()
если вы не подклассифицируете, Activity
и ожидается, что кто-то будет подклассифицировать ваш подкласс.
Состояние, в котором вы сохраняете, onSaveInstanceState()
позже станет доступно при onCreate()
вызове метода. Поэтому используйте onCreate
(и его Bundle
параметр), чтобы восстановить состояние вашей активности.
В качестве обходного пути вы можете сохранить пакет с данными, которые вы хотите поддерживать, в намерении, которое вы используете для запуска действия A.
Intent intent = new Intent(this, ActivityA.class);
intent.putExtra("bundle", theBundledData);
startActivity(intent);
Действие A должно передать это обратно в действие B. Вы должны получить намерение в методе onCreate действия B.
Intent intent = getIntent();
Bundle intentBundle;
if (intent != null)
intentBundle = intent.getBundleExtra("bundle");
// Do something with the data.
Другая идея состоит в том, чтобы создать класс репозитория для хранения состояния активности и чтобы каждое из ваших действий ссылалось на этот класс (возможно, используя одноэлементную структуру). Хотя это, вероятно, больше проблем, чем оно того стоит.
Главное, что если не хранить onSaveInstanceState()
то onRestoreInstanceState()
не будет. Это основное различие между restoreInstanceState()
и onCreate()
. Убедитесь, что вы действительно что-то храните. Скорее всего это ваша проблема.
Я обнаружил, что onSaveInstanceState всегда вызывается, когда на передний план выходит другое Activity. И так же onStop.
Однако onRestoreInstanceState вызывался только тогда, когда также вызывались onCreate и onStart. И onCreate и onStart НЕ всегда вызывались.
Таким образом, похоже, что Android не всегда удаляет информацию о состоянии, даже если Activity перемещается в фоновый режим. Однако он вызывает методы жизненного цикла для сохранения состояния на всякий случай. Таким образом, если состояние не удалено, Android не вызывает методы жизненного цикла для восстановления состояния, поскольку они не нужны.
Рисунок 2 описывает это.
Я думаю, эта ветка была довольно старой. Я просто упомянул еще один случай, который onSaveInstanceState()
также будет вызван, когда вы позвоните Activity.moveTaskToBack(boolean nonRootActivity)
.
Необязательно, чтобы onRestoreInstanceState всегда вызывался после onSaveInstanceState.
Обратите внимание, что: onRestoreInstanceState всегда будет вызываться при повороте активности (когда ориентация не обрабатывается) или при открытии вашей активности, а затем открытии других приложений, чтобы ваш экземпляр активности был удален из памяти ОС.
Из документации Восстановление состояния пользовательского интерфейса активности с использованием сохраненного состояния экземпляра указано как:
Вместо восстановления состояния во время onCreate () вы можете выбрать реализацию onRestoreInstanceState (), которую система вызывает после метода onStart (). Система вызывает onRestoreInstanceState () только при наличии сохраненного состояния для восстановления, поэтому вам не нужно проверять, является ли Bundle нулевым :
ИМО, это более понятный способ, чем проверка на onCreate, и он лучше соответствует принципу единой ответственности.
В моем случае он onRestoreInstanceState
был вызван при восстановлении активности после изменения ориентации устройства. onCreate(Bundle)
был вызван первым, но в пакете не было ключей и значений, которые я установил onSaveInstanceState(Bundle)
.
Сразу после этого onRestoreInstanceState(Bundle)
был вызван пакет с правильными парами "ключ-значение".
Я просто столкнулся с этим и заметил, что в документации есть мой ответ:
«Эта функция никогда не будет вызываться с нулевым состоянием».
В моем случае мне было интересно, почему onRestoreInstanceState не вызывается при первоначальном создании экземпляра. Это также означает, что если вы ничего не сохраните, он не будет вызываться, когда вы перейдете, чтобы восстановить свое представление.
Я могу это сделать (извините, это 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();
}
НАКОНЕЦ-ТО
protected override void OnActivityResult(int iRequestCode, Android.App.Result oResultCode, Intent oIntent)
{
base.OnActivityResult (iRequestCode, oResultCode, oIntent);
iValue = oIntent.Extras.GetInt("MYVALUE", -1); //=> 1234567890
}