Quand exactement onSaveInstanceState () et onRestoreInstanceState () sont-ils appelés?

102

La figure suivante (tirée de la documentation officielle ) décrit le cycle de vie bien connu d'une activité Android:

entrez la description de l'image ici

Par contre, lorsque l'activité est détruite par le système (par exemple parce que la mémoire doit être récupérée), l'état de l'activité est parfois automatiquement sauvegardé et restauré au moyen des méthodes onSaveInstanceState()et onRestoreInstanceState(), comme illustré par la figure suivante (également du document officiel ):

entrez la description de l'image ici

Je suis conscient que ce onSaveInstanceState()n'est pas toujours appelé lorsqu'une activité est sur le point d'être détruite. Par exemple, s'il est détruit parce que l'utilisateur a appuyé sur le bouton «retour», l'état d'activité n'est pas conservé. Mais dans les cas où l'état est enregistré et restauré, et onSaveInstanceState()/ onRestoreInstanceState()est appelé, quand exactement sont-ils appelés ?

Par exemple, selon les chiffres ci-dessus, onRestoreInstanceState()peut être appelé avant onStart(), ou après onStart()mais avant onResume()ou après onResume(). De même, plusieurs possibilités existent pour onSaveInstanceState(). Alors, quand sont-ils appelés exactement?

Idéalement, je voudrais voir un diagramme combiné montrant les états du cycle de vie de l'activité et les méthodes de sauvegarde / restauration , si cela existe.

Luis Mendo
la source
obtenu la réponse finale du document officiel Android, onSaveInstanceState () appelé entre onPause () et onStop ().
Rishi
1
@Rishi Pouvez-vous s'il vous plaît fournir un lien vers ce document?
Luis Mendo
lire Enregistrer l'état de votre activité Paragraphe ici
Rishi
si j'ai raison ou non, veuillez clarifier
Rishi

Réponses:

107

Selon la documentation :

void onRestoreInstanceState (Bundle savedInstanceState)

Cette méthode est appelée entre onStart()et onPostCreate(Bundle).

void onSaveInstanceState (Bundle outState)

Si elle est appelée, cette méthode se produira après onStop () pour les applications ciblant les plates-formes commençant par Build.VERSION_CODES.P. Pour les applications ciblant des versions de plate-forme antérieures, cette méthode se produira avant onStop () et il n'y a aucune garantie quant à savoir si elle se produira avant ou après onPause ().

Steve M
la source
1
Merci. Pourriez-vous s'il vous plaît fournir les liens vers la documentation?
Luis Mendo
Voilà, je ne pense pas non plus qu'il y ait autre chose entre onStart () et onPostCreate (), donc onRestoreInstanceState () est bien défini dans la chaîne.
Steve M
Merci beaucoup. Cela clarifie le problème
Luis Mendo
1
@SteveM "Il n'y a aucune garantie quant à savoir si cela se produira avant ou après onPause ()" Cela signifie-t-il que si nous essayons d'accéder à une vue (pour obtenir une valeur à sauvegarder, comme un index à partir d'une liste), nous pourrions rencontrer NullPointerExceptions?
Tiago
3
Ensuite, qu'est-ce qui est recommandé, enregistrer une structure de données dans onPause et la restaurer dans onResume à la place dans onSaveInstanceState et onRestoreInstanceState?
Gödel77
18

Selon doc1 et doc2

onSaveInstanceState

Avant Honeycomb, les activités n'étaient considérées comme tuables qu'après leur mise en pause, ce qui signifie que onSaveInstanceState () était appelé immédiatement avant onPause (). Cependant, à partir de Honeycomb, les activités sont considérées comme pouvant être supprimées uniquement après leur arrêt, ce qui signifie que onSaveInstanceState () sera désormais appelée avant onStop () au lieu de juste avant onPause ().

onRestoreInstanceState

Cette méthode est appelée entre onStart () et onPostCreate (Bundle) lorsque l'activité est en cours de réinitialisation à partir d'un état précédemment enregistré

Développeur Android
la source
aimé la façon dont vous avez décrit les scénarios sur différentes versions d'Android
Jimit Patel
14

En plus des réponses déjà publiées, il y a un changement subtil introduit dans Android P, à savoir:

void onSaveInstanceState (Bundle outState)

Si elle est appelée, cette méthode se produira AFTER onStop() pour les applications ciblant les plates - formes commençant par P . Pour les applications ciblant des versions de plate-forme antérieures, cette méthode se produira avant onStop()et il n'y a aucune garantie quant à savoir si elle se produira avant ou après onPause().

Source: documents

Quant à savoir pourquoi ce changement est introduit, voici la réponse:

... afin qu'une application puisse effectuer en toute sécurité des transactions fragmentées dans onStop()et pourra enregistrer l'état persistant plus tard.

Source: documents

azizbek
la source
Salut, excellent commentaire. Savez-vous comment se comportera l'application qui cible P mais s'exécute sur une API inférieure? Identique à l'application ciblant une API inférieure ou sera-t-elle cohérente entre les API et conservera le comportement de «ciblage de l'API»?
Filipkowicz
@Filipkowicz, Do you know how will behave app that target P but runs on lower api?tant que l'application est exécutée sur, disons M, la version d'Android que cet appareil possède ne contient pas de modifications, qui sont introduites dans P, ce qui signifie que peu importe que vous ayez spécifié la cible, Pvous ne verrez pas différent pour les appareils pré-P. J'espère que ça répond à ta question.
azizbekian
Je me sens tellement détendu aujourd'hui après avoir lu cette réponse, car je suivais le cours gratuit Android sur Udacity et ils ont toujours l'ancienne version des didacticiels qui indiquent dans la leçon 5 exercice 8 que les méthodes onStop et onDestroy ne devraient pas être là dans le textView affiché. Mais je ne savais pas que c'était pour les anciennes versions d'Android et j'exécutais mon application sur Android Pie et recevais la méthode onStop dans mon textView. Merci beaucoup. Enfin se sentir bien.
Sandhu
6

Ceci est une information supplémentaire pour onSaveInstanceState (Bundle)

à partir de documents

Ne confondez pas cette méthode avec des rappels de cycle de vie d'activité tels que onPause (), qui est toujours appelé lorsqu'une activité est placée en arrière-plan ou en voie de destruction, ou onStop () qui est appelé avant la destruction. Un exemple d'appels de onPause () et onStop () et non de cette méthode est lorsqu'un utilisateur revient de l'activité B à l'activité A: il n'est pas nécessaire d'appeler onSaveInstanceState (Bundle) sur B car cette instance particulière ne sera jamais restaurée , donc le système évite de l'appeler. Un exemple lorsque onPause () est appelé et non onSaveInstanceState (Bundle) est lorsque l'activité B est lancée devant l'activité A: le système peut éviter d'appeler onSaveInstanceState (Bundle) sur l'activité A si elle n'est pas tuée pendant la durée de vie de B depuis l'état de l'interface utilisateur de A restera intact.

C'est donc l'implémentation par défaut pour ..

L'implémentation par défaut prend en charge la plupart de l'état de l'interface utilisateur par instance pour vous en appelant onSaveInstanceState () sur chaque vue de la hiérarchie qui a un identifiant, et en enregistrant l'identifiant de la vue actuellement focalisée (qui est tout restauré par le implémentation par défaut de onRestoreInstanceState (Bundle)). Si vous remplacez cette méthode pour enregistrer des informations supplémentaires non capturées par chaque vue individuelle, vous souhaiterez probablement appeler l'implémentation par défaut, sinon soyez prêt à enregistrer vous-même tout l'état de chaque vue.

Mahmoud Mzz
la source
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);
} 

// Ce rappel est appelé uniquement lorsqu'il existe une instance enregistrée précédemment enregistrée à l'aide de // onSaveInstanceState (). Nous restaurons un état dans onCreate () tandis que nous pouvons éventuellement restaurer // un autre état ici, éventuellement utilisable après la fin de onStart (). // Le bundle savedInstanceState est le même que celui utilisé dans 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
la source
Excusez-moi, comment cela répond-il à la question de savoir quand les méthodes de sauvegarde / restauration sont appelées exactement ?
Luis Mendo