Я намагаюся зберегти та відновити стан 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
параметр) для відновлення стану вашої діяльності.
Як вирішення, ви можете зберігати пакет із даними, які ви хочете підтримувати, у намірі, який ви використовуєте для запуску діяльності А.
Intent intent = new Intent(this, ActivityA.class);
intent.putExtra("bundle", theBundledData);
startActivity(intent);
Діяльність A повинна буде повернути це назад у Activity 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 завжди викликається, коли на перший план виходить інша діяльність. Так і є наСтопі.
Однак onRestoreInstanceState викликався лише тоді, коли були також викликані onCreate і onStart. І, onCreate і onStart НЕ завжди викликалися.
Тому здається, що Android не завжди видаляє інформацію про стан, навіть якщо активність рухається на другий план. Однак він закликає методи життєвого циклу для збереження стану просто бути безпечними. Таким чином, якщо стан не видалено, Android не закликає методи життєвого циклу відновити стан, оскільки вони не потрібні.
Малюнок 2 описує це.
Не обов'язково, щоб onRestoreInstanceState завжди викликався після onSaveInstanceState.
Зауважте, що: onRestoreInstanceState завжди буде викликатися, коли активність повертається (коли орієнтація не обробляється) або відкривається активність, а потім відкриваються інші додатки, щоб екземпляр вашої діяльності очищався від пам'яті ОС.
З документації відновлення стану інтерфейсу діяльності з використанням збереженого стану екземпляра зазначено як:
Замість того, щоб відновити стан під час onCreate (), ви можете вибрати впровадження OnRestoreInstanceState (), яке система викликає після методу onStart (). Система викликаєReRerereInstanceState (), тільки якщо є збережений стан для відновлення, тому вам не потрібно перевіряти, чи пакет недійсний :
IMO, це більш зрозумілий спосіб, ніж перевірка цього на onCreate, і він краще відповідає принципу єдиної відповідальності.
У моєму випадку onRestoreInstanceState
викликали, коли активність реконструювали після зміни орієнтації пристрою. onCreate(Bundle)
був викликаний першим, але в комплекті не було ключа / значення, яке я встановив onSaveInstanceState(Bundle)
.
Одразу після onRestoreInstanceState(Bundle)
цього викликувались пакетом, який мав правильний ключ / значення.
Я просто натрапив на це і помітив, що в документації була моя відповідь:
"Ця функція ніколи не буде викликана зі станом нуля."
У моєму випадку мені було цікаво, чому onRestoreInstanceState не викликали початкової інстанції. Це також означає, що якщо ви нічого не зберігаєте, воно не зателефонує, коли ви перейдете до реконструкції перегляду.
Я можу зробити так (вибачте, що це # не 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
}