Estoy tratando de guardar y restaurar el estado de un Activity
usando los métodos onSaveInstanceState()
y onRestoreInstanceState()
.
El problema es que nunca ingresa al onRestoreInstanceState()
método. ¿Alguien puede explicarme por qué es esto?
Estoy tratando de guardar y restaurar el estado de un Activity
usando los métodos onSaveInstanceState()
y onRestoreInstanceState()
.
El problema es que nunca ingresa al onRestoreInstanceState()
método. ¿Alguien puede explicarme por qué es esto?
Respuestas:
Por lo general, restaura su estado onCreate()
. Es posible restaurarlo onRestoreInstanceState()
también, pero no es muy común. ( onRestoreInstanceState()
se llama después onStart()
, mientras que onCreate()
se llama antes onStart()
.
Use los métodos put para almacenar valores en onSaveInstanceState()
:
protected void onSaveInstanceState(Bundle icicle) {
super.onSaveInstanceState(icicle);
icicle.putLong("param", value);
}
Y restaurar los valores en onCreate()
:
public void onCreate(Bundle icicle) {
if (icicle != null){
value = icicle.getLong("param");
}
}
onRestoreInstanceState()
solo se llama cuando se recrea la actividad después de que el sistema operativo la eliminó . Tal situación ocurre cuando:
Por el contrario: si está en su actividad y Back
presiona el botón en el dispositivo, su actividad se termina () edita (es decir, piensa que es una aplicación de escritorio existente) y la próxima vez que inicie su aplicación, se iniciará "fresca", es decir, sin estado guardado porque lo saliste intencionalmente cuando golpeaste Back
.
Otra fuente de confusión es que cuando una aplicación pierde el foco onSaveInstanceState()
se llama a otra aplicación, pero cuando navegas de regreso a tu aplicación, es onRestoreInstanceState()
posible que no se llame. Este es el caso descrito en la pregunta original, es decir, si su actividad NO se eliminó durante el período en que otra actividad estaba al frente onRestoreInstanceState()
NO se llamará porque su actividad está prácticamente "viva".
En general, como se indica en la documentación para onRestoreInstanceState()
:
La mayoría de las implementaciones simplemente usarán onCreate (Bundle) para restaurar su estado, pero a veces es conveniente hacerlo aquí después de que se haya realizado toda la inicialización o para permitir que las subclases decidan si usarán su implementación predeterminada. La implementación predeterminada de este método realiza una restauración de cualquier estado de vista que previamente haya sido congelado por onSaveInstanceState (Bundle).
Mientras lo leo: no hay razón para anular a onRestoreInstanceState()
menos que esté subclasificando Activity
y se espera que alguien subclasifique su subclase.
El estado en el que guarda onSaveInstanceState()
está disponible más tarde en la onCreate()
invocación del método. Entonces use onCreate
(y su Bundle
parámetro) para restaurar el estado de su actividad.
Como solución alternativa, puede almacenar un paquete con los datos que desea mantener en la intención que utiliza para iniciar la actividad A.
Intent intent = new Intent(this, ActivityA.class);
intent.putExtra("bundle", theBundledData);
startActivity(intent);
La Actividad A tendría que devolver esto a la Actividad B. Recuperaría la intención en el método onCreate de la Actividad B.
Intent intent = getIntent();
Bundle intentBundle;
if (intent != null)
intentBundle = intent.getBundleExtra("bundle");
// Do something with the data.
Otra idea es crear una clase de repositorio para almacenar el estado de la actividad y hacer que cada una de sus actividades haga referencia a esa clase (posible utilizando una estructura singleton). Sin embargo, hacerlo probablemente sea más problemático de lo que vale.
Lo principal es que si no almacena en, onSaveInstanceState()
entonces onRestoreInstanceState()
no será llamado. Esta es la principal diferencia entre restoreInstanceState()
y onCreate()
. Asegúrate de guardar algo realmente. Lo más probable es que este sea tu problema.
Descubrí que onSaveInstanceState siempre se llama cuando otra actividad aparece en primer plano. Y también lo es onStop.
Sin embargo, onRestoreInstanceState solo se llamó cuando onCreate y onStart también se llamaron. Y, onCreate y onStart NO siempre se llamaban.
Por lo tanto, parece que Android no siempre elimina la información de estado, incluso si la Actividad se mueve a un segundo plano. Sin embargo, llama a los métodos del ciclo de vida para guardar el estado solo para estar seguro. Por lo tanto, si el estado no se elimina, Android no llama a los métodos del ciclo de vida para restaurar el estado, ya que no son necesarios.
La figura 2 describe esto.
No es necesario que onRestoreInstanceState siempre se llame después de onSaveInstanceState.
Tenga en cuenta que: onRestoreInstanceState siempre se llamará, cuando se gira la actividad (cuando no se maneja la orientación) o abra su actividad y luego abra otras aplicaciones para que el sistema operativo borre su instancia de actividad de la memoria.
De la documentación Restaurar el estado de la IU de la actividad utilizando el estado de instancia guardado se indica como:
En lugar de restaurar el estado durante onCreate (), puede optar por implementar onRestoreInstanceState (), que el sistema llama después del método onStart (). El sistema llama a onRestoreInstanceState () solo si hay un estado guardado para restaurar, por lo que no necesita verificar si el paquete es nulo :
En mi opinión, esta es una forma más clara que verificar esto en onCreate, y se ajusta mejor con el principio de responsabilidad única.
En mi caso, onRestoreInstanceState
se llamó cuando la actividad se reconstruyó después de cambiar la orientación del dispositivo. onCreate(Bundle)
se llamó primero, pero el paquete no tenía la clave / los valores que configuré onSaveInstanceState(Bundle)
.
Justo después, onRestoreInstanceState(Bundle)
fue llamado con un paquete que tenía la clave / valores correctos.
Me encontré con esto y me di cuenta de que la documentación tenía mi respuesta:
"Esta función nunca se llamará con un estado nulo".
En mi caso, me preguntaba por qué no se llamaba a onRestoreInstanceState en la instanciación inicial. Esto también significa que si no almacena nada, no se llamará cuando vaya a reconstruir su vista.
Puedo hacer eso (lo siento, es C #, no Java, pero no es un problema ...):
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);
}
Y EN TU ACTIVIDAD PARA EL RESULTADO
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();
}
FINALMENTE
protected override void OnActivityResult(int iRequestCode, Android.App.Result oResultCode, Intent oIntent)
{
base.OnActivityResult (iRequestCode, oResultCode, oIntent);
iValue = oIntent.Extras.GetInt("MYVALUE", -1); //=> 1234567890
}