¿Cuándo exactamente se llama a onSaveInstanceState () y onRestoreInstanceState ()?

102

La siguiente figura (del documento oficial ) describe el ciclo de vida conocido de una actividad de Android:

ingrese la descripción de la imagen aquí

Por otro lado, cuando el sistema destruye la actividad (por ejemplo, porque es necesario recuperar la memoria), el estado de la actividad a veces se guarda y restaura automáticamente mediante los métodos onSaveInstanceState()y onRestoreInstanceState(), como se ilustra en la siguiente figura (también del documento oficial ):

ingrese la descripción de la imagen aquí

Soy consciente de que onSaveInstanceState()está no siempre llama cuando una actividad está a punto de ser destruido. Por ejemplo, si se destruye porque el usuario ha presionado el botón "Atrás", el estado de actividad no se conserva. Sin embargo, en los casos en que el estado está guardada y restaurada, y onSaveInstanceState()/ onRestoreInstanceState()ser llamado, cuando exactamente cómo se llaman ?

Por ejemplo, de acuerdo con las figuras anteriores, onRestoreInstanceState()podría llamarse antes onStart()o después, onStart()pero antes onResume()o después onResume(). Del mismo modo, existen varias posibilidades para onSaveInstanceState(). Entonces, ¿cuándo se llaman exactamente?

Idealmente, lo que me gustaría es ver un diagrama combinado que muestre los estados del ciclo de vida de la actividad y los métodos de guardar / restaurar , si es que existe.

Luis Mendo
fuente
Obtuve la respuesta final del documento oficial de Android, onSaveInstanceState () llamado entre onPause () y onStop ().
Rishi
1
@Rishi ¿Puede proporcionar un enlace a ese documento?
Luis Mendo
lea Guarde su párrafo de estado de actividad allí
Rishi
si estoy en lo cierto o no, aclare
Rishi

Respuestas:

107

Según la documentación :

void onRestoreInstanceState (Paquete guardadoInstanceState)

Este método se llama entre onStart()y onPostCreate(Bundle).

void onSaveInstanceState (Bundle outState)

Si se llama, este método se producirá después de onStop () para las aplicaciones que se dirigen a plataformas que comienzan con Build.VERSION_CODES.P. Para las aplicaciones destinadas a versiones anteriores de la plataforma, este método ocurrirá antes de onStop () y no hay garantías de si ocurrirá antes o después de onPause ().

Steve M
fuente
1
Gracias. ¿Podría proporcionar los enlaces a la documentación?
Luis Mendo
Ahí lo tienes, tampoco creo que haya nada más entre onStart () y onPostCreate (), por lo que onRestoreInstanceState () está bien definido en la cadena.
Steve M
Muchas gracias. Esto aclara el problema
Luis Mendo
1
@SteveM "No hay garantías sobre si ocurrirá antes o después de onPause ()" ¿Eso significa que si intentamos acceder a una vista (para obtener algún valor para guardar, como un índice de una vista de lista) podríamos encontrarnos con NullPointerExceptions?
Tiago
3
Entonces, ¿qué se recomienda, guardar una estructura de datos en onPause y restaurarla en onResume en lugar de onSaveInstanceState y onRestoreInstanceState?
Gödel77
18

Según doc1 y doc2

onSaveInstanceState

Antes de Honeycomb, las actividades no se consideraban eliminables hasta después de haber sido pausadas, lo que significa que onSaveInstanceState () se llamaba inmediatamente antes de onPause (). Sin embargo, a partir de Honeycomb, las actividades se consideran eliminables solo después de que se hayan detenido, lo que significa que ahora se llamará a onSaveInstanceState () antes de onStop () en lugar de inmediatamente antes de onPause ().

onRestoreInstanceState

Este método se llama entre onStart () y onPostCreate (Bundle) cuando la actividad se reinicializa desde un estado guardado previamente

Desarrollador de Android
fuente
Me
14

Además de las respuestas ya publicadas, se ha introducido un cambio sutil en Android P, que es:

void onSaveInstanceState (Bundle outState)

Si se llama, este método se producirá después onStop() para aplicaciones dirigidas a las plataformas que empiezan por P . Para las aplicaciones destinadas a versiones anteriores de la plataforma, este método ocurrirá antes onStop()y no hay garantías de si ocurrirá antes o después onPause().

Fuente: docs

En cuanto a por qué se introduce este cambio, aquí está la respuesta:

... para que una aplicación pueda realizar transacciones de fragmentos de forma segura onStop()y pueda guardar el estado persistente más adelante.

Fuente: docs

azizbeko
fuente
Hola, gran comentario. ¿Sabes cómo se comportará la aplicación que apunta a P pero se ejecuta en una API inferior? ¿Igual que la aplicación orientada a api inferior o será coherente en todas las api y mantendrá el comportamiento de "api de orientación"?
Filipkowicz
@Filipkowicz, Do you know how will behave app that target P but runs on lower api?siempre que la aplicación se ejecute en, por ejemplo, M, entonces la versión de Android que tiene este dispositivo no contiene cambios, que se introducen en P, lo que significa que, independientemente de que haya especificado el objetivo P, no verá diferente para dispositivos pre-P. Espero que esto responda a su pregunta.
azizbekian
Me siento tan relajado hoy después de leer esta respuesta, porque estaba haciendo el curso gratuito de Android en Udacity y todavía tienen la versión anterior de los tutoriales que dicen en la lección 5 ejercicio 8 que los métodos onStop y onDestroy no deberían estar allí en el visualizado textView. Pero no sabía que era para las versiones anteriores de Android y estaba ejecutando mi aplicación en Android Pie y obtenía el método onStop en mi textView. Muchas gracias. Finalmente me siento bien.
Sandhu
6

Esta es una información adicional para onSaveInstanceState (Bundle)

de documentos

No confunda este método con devoluciones de llamada del ciclo de vida de la actividad, como onPause (), que siempre se llama cuando una actividad se coloca en segundo plano o en camino de su destrucción, o onStop (), que se llama antes de la destrucción. Un ejemplo de cuando se llama a onPause () y onStop () y no a este método es cuando un usuario navega de regreso de la actividad B a la actividad A: no hay necesidad de llamar a onSaveInstanceState (Bundle) en B porque esa instancia en particular nunca se restaurará , por lo que el sistema evita llamarlo. Un ejemplo cuando se llama a onPause () y no a onSaveInstanceState (Bundle) es cuando la actividad B se inicia frente a la actividad A: el sistema puede evitar llamar a onSaveInstanceState (Bundle) en la actividad A si no se mata durante la vida de B ya que el estado de la interfaz de usuario de A permanecerá intacto.

Entonces es una implementación predeterminada para ...

La implementación predeterminada se encarga de la mayor parte del estado de la interfaz de usuario por instancia llamando a onSaveInstanceState () en cada vista de la jerarquía que tiene una identificación y guardando la identificación de la vista actualmente enfocada (todo lo cual es restaurado por el implementación predeterminada de onRestoreInstanceState (Bundle)). Si anula este método para guardar información adicional no capturada por cada vista individual, probablemente querrá llamar a la implementación predeterminada; de lo contrario, prepárese para guardar todo el estado de cada vista usted mismo.

Mahmoud Mzz
fuente
0
String activityState;
@Override 
public void onCreate(Bundle savedInstanceState) {
// call the super class onCreate to complete the creation of activity like 
// the view hierarchy 
super.onCreate(savedInstanceState);

// recovering the instance state 
if (savedInstanceState != null) {
     activityState = savedInstanceState.getString(STATE_KEY);
 } 

   setContentView(R.layout.main_activity);
   mTextView = (TextView) findViewById(R.id.text_view);
} 

// Esta devolución de llamada se llama solo cuando hay una instancia guardada previamente guardada usando // onSaveInstanceState (). Restauramos algún estado en onCreate () mientras que opcionalmente podemos restaurar // otro estado aquí, posiblemente utilizable después de que se haya completado onStart (). // El paquete SavedInstanceState es el mismo que se usa en onCreate ().

@Override 
public void onRestoreInstanceState(Bundle savedInstanceState) {
 mTextView.setText(savedInstanceState.getString(STATE_KEY));
  } 


// invoked when the activity may be temporarily destroyed, save the instance 
//state here 
//this method will be called before onstop

@Override 
 public void onSaveInstanceState(Bundle outState) {
    outState.putString(STATE_KEY, activityState);

    // call superclass to save any view hierarchy 
    super.onSaveInstanceState(outState);
} 
parvez rafi
fuente
Disculpe, ¿cómo responde esto a la pregunta de cuándo se llaman exactamente los métodos de guardar / restaurar ?
Luis Mendo