OnSaveInstanceState () y onRestoreInstanceState ()

Estoy tratando de guardar y restaurar el estado de una Activity utilizando los métodos onSaveInstanceState() y onRestoreInstanceState() .

El problema es que nunca entra en el método onRestoreInstanceState() . ¿Puede alguien explicarme por qué es esto?

Normalmente restaura su estado en onCreate() . Es posible restaurarlo en onRestoreInstanceState() , pero no es muy común. ( onRestoreInstanceState() se llama después de onStart() , mientras que onCreate() se llama antes onStart() .

Utilice 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"); } } 

No es necesario almacenar los estados de vista, ya que se almacenan automáticamente llamando a super.onSaveInstanceState (icicle) ;.

onRestoreInstanceState() se llama sólo al recrear la actividad después de que fue onRestoreInstanceState() por el sistema operativo. Tal situación ocurre cuando:

  • Orientación del dispositivo cambia (su actividad es destruida y recreada)
  • Hay otra actividad delante de la tuya y en algún momento el OS mata tu actividad para liberar memoria (por ejemplo). La próxima vez que inicie su actividad onRestoreInstanceState() será llamado.

Por el contrario: si estás en tu actividad y Back botón Back en el dispositivo, la actividad es finish () ed (es decir, piensas que sale como aplicación de escritorio) y la próxima vez que inicies tu aplicación, se inicia "fresh", es decir Sin guardar el estado porque intencionalmente salió cuando se pulsa Back .

Otra fuente de confusión es que cuando una aplicación pierde foco a otra aplicación onSaveInstanceState() se llama, pero cuando vuelve a navegar a su aplicación onRestoreInstanceState() no se puede llamar. Este es el caso descrito en la pregunta original, es decir, si su actividad NO fue asesinada durante el período en que otra actividad estaba en frente onRestoreInstanceState() NO se llamará porque su actividad es prácticamente "viva".

En conjunto, como se indica en la documentación de 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 utilizar la implementación predeterminada. La implementación predeterminada de este método realiza una restauración de cualquier estado de vista que previamente había sido congelado por onSaveInstanceState (Bundle).

Como lo leí: No hay razón para anular onRestoreInstanceState() menos que esté subclase Activity y se espera que alguien subclase su subclase.

El estado que guarda en onSaveInstanceState() encuentra disponible posteriormente en la invocación del método onCreate() . Así que utilice onCreate (y su parámetro Bundle ) para restaurar el estado de su actividad.

Creo que este hilo era bastante viejo. Acabo de mencionar otro caso, que onSaveInstanceStatus() también se llamará, es cuando se llama Activity.moveTaskToBack(boolean nonRootActivity) .

Lo principal es que si no almacena en onSaveInstanceState() entonces onRestoreInstanceState() no será llamado. Esta es la diferencia principal entre restoreInstanceState() y onCreate() . Asegúrese de que realmente almacena algo. Lo más probable es que este sea su problema.

Encontré que onSaveInstanceState se llama siempre cuando otra actividad viene al primero plano. Y así es onStop.

Sin embargo, onRestoreInstanceState se llamó sólo cuando onCreate y onStart también se llamaron. Y, onCreate y onStart no siempre fueron llamados.

Por lo tanto, parece que Android no siempre elimina la información de estado incluso si la Actividad se mueve al fondo. Sin embargo, llama a los métodos de ciclo de vida para guardar el estado sólo para ser seguro. Por lo tanto, si el estado no se elimina, Android no llama a los métodos de ciclo de vida para restaurar el estado, ya que no son necesarios.

La Figura 2 describe esto.

Como solución, puede almacenar un lote con los datos que desea mantener en el intento 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 pasar esto a la Actividad B. Usted 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 (posiblemente utilizando una estructura de singleton). Sin embargo, hacerlo probablemente sea más problemático de lo que vale la pena.

Si está manejando los cambios de orientación de la actividad con android:configChanges="orientation|screenSize" y onConfigurationChanged(Configuration newConfig) , onRestoreInstanceState() no será llamado.

No es necesario que onRestoreInstanceState siempre se llamará después de onSaveInstanceState.

Tenga en cuenta que: onRestoreInstanceState siempre se llamará, cuando se rota la actividad (cuando no se maneja la orientación) o se abre la actividad y luego se abren otras aplicaciones para que la instancia de actividad se borre de la memoria por OS.

En mi caso, onRestoreInstanceState fue llamado cuando la actividad fue reconstruida después de cambiar la orientación del dispositivo. onCreate(Bundle) se llamó primero, pero el paquete no tenía los valores / clave que establecía con onSaveInstanceState(Bundle) .

Justo después, onRestoreInstanceState(Bundle) se llamó con un paquete que tenía la clave correcta / valores.

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."

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

En mi caso, me preguntaba por qué el onRestoreInstanceState no estaba siendo invocado 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 así (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 SU ACTIVIDAD PARA 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 } 
  • Llamar findViewById () desde fuera de una actividad
  • Pantalla secundaria de Android: persistencia a través de la invocación de actividad
  • Cómo setSupportActionBar en una vista que extiende LifecycleActivity
  • ¿Cómo puedo enviar un mensaje de HostApduService a una actividad?
  • Ciclo de vida de la actividad de Android
  • Android: Obtener "No se puede cargar la lista AVD:" error en el momento de la ejecución
  • ¿Cómo puedo iniciar una nueva actividad de Android con una cadena?
  • ¿Cómo auto desplazarse hasta Recycler ver en Android?
  • Android Instrumentaion: ¿Cómo puedo volver a una Actividad lanzada anteriormente?
  • La actividad continúa después de terminar ();
  • Fab.show () no animado por primera vez después de inicializar nueva actividad
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.