Guardando el estado de una actividad

Cuando el usuario ha estado utilizando una actividad, y tras cambiar a otras, regresa a la primera, lo habitual es que esta permanezca en memoria y continúe su ejecución sin alteraciones. Como hemos explicado, en situaciones de escasez de memoria, es posible que el sistema haya eliminado el proceso que ejecutaba la actividad. En este caso, el proceso será creado de nuevo, pero se habrá perdido su estado, es decir, se habrá perdido el valor de sus variables y el puntero de programa. Como consecuencia, si el usuario estaba a mitad de un proceso de edición o estaba reproduciendo un audio en un punto determinado perderá esta información. En este apartado estudiaremos un mecanismo sencillo que nos proporciona Android para resolver este problema.

NOTA:Cuando se ejecuta una actividad sensible a la inclinación del teléfono, es decir puede verse en horizontal o en vertical, se presenta un problema similar al anterior. La actividad es destruida y vuelta a construir con las nuevas dimensiones de pantalla y por lo tanto se llama de nuevo al método onCreate. Antes de que la actividad sea destruida también resulta fundamental guardar su estado.

video[ Tutorial] Guardar el estado de las actividades en  Android

Para guardar el estado de una actividad has de utilizar los siguientes dos métodos:

onSaveInstanceState(Bundle): Invoca el sistema cuando ha de destruir una actividad, que más adelante ha de restaurar (por cambiar su inclinación o por falta de memoria), para  permitir a la actividad guardar su estado.

onRestoreInstanceState(Bundle): Se invoca cuando se restaura la actividad para recuperar el estado guardado por onSaveInstanceState().

NOTA: Nunca utilices el método onSaveInstanceState() para guardar los datos generados por una actividad (como guardar un formulario en una base de datos). Este método es llamado cuando el sistema ha de destruir una actividad que va a ser recuperada en un futuro. Si esta actividad es destruida llamando a  finish() o pulsando el botón atrás, el método  onSaveInstanceState() no será llamado. Para guardar estos datos utiliza onPause() o onStop().

Veamos un ejemplo de lo sencillo que resulta guardar la información de una variable tipo cadena de caracteres y entero.

String var;
int pos;

@Override protected void onSaveInstanceState(Bundle guardarEstado) {
   super.onSaveInstanceState(guardarEstado);
   guardarEstado.putString("variable", var);
   guardarEstado.putInt("posicion", pos);
}

@Override protected void onRestoreInstanceState(Bundle recEstado) {
   super.onRestoreInstanceState(recEstado);
   var = recEstado.getString("variable");
   pos = recEstado.getInt("posicion");
} 
var v: String? = null
var pos: Int = 0

override fun onSaveInstanceState(guardarEstado: Bundle) {
   super.onSaveInstanceState(guardarEstado)
   guardarEstado.putString("variable", v)
   guardarEstado.putInt("posicion", pos)
}

override fun onRestoreInstanceState(recEstado: Bundle) {
   super.onRestoreInstanceState(recEstado)
   v = recEstado.getString("variable")
   pos = recEstado.getInt("posicion")
} 

Práctica: Guardando el estado enla actividad inicial.

1. Ejecuta el proyecto Asteroides o Mis Lugares.<

2. Cambia de orientación el teléfono. Observarás como la música se reinicia cada vez que lo haces.

3. Utilizando los métodos para guardar el estado de una actividad, trata de que cuando se voltea el teléfono, el audio continúe en el mismo punto de reproducción. Puedes utilizar los siguientes métodos:

int pos = mp.getCurrentPosition();
mp.seekTo(pos);

4. Verifica el resultado.
 

Solución: A continuación se muestra una posible solución al ejercicio :

@Override protected void onSaveInstanceState(Bundle estadoGuardado){
   super.onSaveInstanceState(estadoGuardado);
   if (mp != null) {
      int pos = mp.getCurrentPosition();
      estadoGuardado.putInt("posicion", pos);
   }
}

@Override protected void onRestoreInstanceState(Bundle estadoGuardado){
   super.onRestoreInstanceState(estadoGuardado);
   if (estadoGuardado != null && mp != null) {
      int pos = estadoGuardado.getInt("posicion");
      mp.seekTo(pos);
   }
} 
override fun onSaveInstanceState(estadoGuardado: Bundle) {
   super.onSaveInstanceState(estadoGuardado)
   if (mp != null) {
      val pos = mp.getCurrentPosition()
      estadoGuardado.putInt("posicion", pos)
   }
}

override fun onRestoreInstanceState(estadoGuardado: Bundle?) {
   super.onRestoreInstanceState(estadoGuardado)
   if (estadoGuardado != null && mp != null) {
      val pos = estadoGuardado.getInt("posicion")
      mp.seekTo(pos)
   }
} 

Preguntas de repaso: Guardar estado