2010-11-04 2 views
123

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

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

+8

Я знаю, что это довольно старая нить, но я подумал, что это может помочь кому-то luking для более информативной статьи о штатах Android, которые действительно запутывают. Вот ссылка: http://www.eigo.co.uk/Managing-State-in-an-Android-Activity.aspx –

+1

@Nitin: спасибо, что поделились ссылкой ... это прояснило мне несколько вещей +1 – Taliadon

ответ

6

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

+3

Можете ли вы привести мне пример (фрагмент кода)? – BlaBRA

177

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

Используйте методы пут для хранения значений в 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"); 
    } 
} 

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

+2

проблема заключается в том, что я использую startActivity для возврата к активности A. При возврате к активности B объект является null icicle. – BlaBRA

+5

Если я правильно понимаю, это то, что вы делаете: из B вы вызываете startActivity (A). Затем из A вы вызываете финиш(), чтобы вернуться к B. Правильно? В этом случае Ваша первая деятельность, B не будет уничтожена, и ни onCreate(), ни onRestoreInstanceState() не будут вызваны. Эти методы вызывают только тогда, когда это необходимо, то есть когда действие было уничтожено и нуждается в воссоздании системой. – Robert

+4

Я должен добавить, что ваша первая активность, B, может быть уничтожена из-за низких условий памяти. Это вызовет onCreate и onRestoreInstanceState. – Robert

141

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

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

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

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

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

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

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

+3

yeh это кажется правильным, но это отстой. imo он также должен запускаться при возврате к активности из другого вида деятельности. есть много ситуаций, в которых вам это нужно. – masi

+4

@masi уже есть другие методы, вызываемые в Activity, когда пользователь возвращается к нему (из другого действия). OnSave/RestoreInstanceState() используется для другой конкретной цели, вот и все. – superjos

2

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

3

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

+1

onRestoreInstanceState() будет вызываться, даже если вы ничего не храните в OnSaveInstanceState() – abh22ishek

0

В моем случаебыл вызван, когда активность была восстановлена ​​после изменения ориентации устройства. onCreate(Bundle) был вызван первым, но у пучка не было ключа/значений, заданных с onSaveInstanceState(Bundle).

Сразу после, onRestoreInstanceState(Bundle) был вызван с пакетом с правильными ключами/значениями.

3

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

Однако onRestoreInstanceState был вызван только в том случае, когда onCreate и onStart также были вызваны. И, onCreate и onStart не всегда вызывались.

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

Figure 2 описывает это.

4

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

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

активность А было бы передать это обратно активность B. Вы будет извлекать намерение в методе onCreate Activity B.

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

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

1

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

0

Я просто побежал в это и заметил, что документация была мой ответ:

«Эта функция никогда не будет вызвана с нулевым состоянием."

https://developer.android.com/reference/android/view/View.html#onRestoreInstanceState(android.os.Parcelable)

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

0

Я могу сделать так (извините это 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 
} 
1

Это не обязательно, что onRestoreInstanceState всегда будет вызываться после onSaveInstanceState.

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

Смежные вопросы