Wann genau werden onSaveInstanceState () und onRestoreInstanceState () aufgerufen?

102

Die folgende Abbildung (aus dem offiziellen Dokument ) beschreibt den bekannten Lebenszyklus einer Android-Aktivität:

Geben Sie hier die Bildbeschreibung ein

Wenn andererseits die Aktivität vom System zerstört wird (z. B. weil Speicher zurückgefordert werden muss), wird der Status der Aktivität manchmal automatisch gespeichert und mithilfe der Methoden wiederhergestelltonSaveInstanceState() und onRestoreInstanceState(), wie in der folgenden Abbildung dargestellt (auch) aus dem offiziellen Dokument ):

Geben Sie hier die Bildbeschreibung ein

Ich bin mir bewusst , dass onSaveInstanceState()ist nicht immer aufgerufen , wenn eine Aktivität im Begriff ist , zerstört werden. Wenn es beispielsweise zerstört wird, weil der Benutzer die Schaltfläche "Zurück" gedrückt hat, bleibt der Aktivitätsstatus nicht erhalten. Aber in den Fällen , wenn der Zustand wird gespeichert und wiederhergestellt, und onSaveInstanceState()/ onRestoreInstanceState()aufgerufen, wann genau werden sie genannt ?

Zum Beispiel könnte gemäß den obigen Figuren onRestoreInstanceState()vorher onStart()oder nachher, onStart()aber vorher onResume()oder nachher aufgerufen werden onResume(). Ebenso gibt es mehrere Möglichkeiten für onSaveInstanceState(). Wann werden sie genau genannt?

Im Idealfall möchte ich ein kombiniertes Diagramm sehen, das die Aktivitätslebenszykluszustände und die Speicher- / Wiederherstellungsmethoden zeigt , falls vorhanden.

Luis Mendo
quelle
Die endgültige Antwort wurde vom offiziellen Android-Dokument onSaveInstanceState () erhalten, das zwischen onPause () und onStop () aufgerufen wurde.
Rishi
1
@Rishi Können Sie bitte einen Link zu diesem Dokument bereitstellen?
Luis Mendo
Lesen Sie Speichern Sie Ihren Aktivitätsstatus Absatz dort
Rishi
ob ich richtig bin oder nicht, bitte klären
Rishi

Antworten:

107

Gemäß der Dokumentation :

void onRestoreInstanceState (Bundle savedInstanceState)

Diese Methode wird zwischen onStart()und aufgerufen onPostCreate(Bundle).

void onSaveInstanceState (Bundle outState)

Wenn diese Methode aufgerufen wird, wird sie nach onStop () für Anwendungen ausgeführt, die auf Plattformen abzielen, die mit Build.VERSION_CODES.P beginnen. Für Anwendungen, die auf frühere Plattformversionen abzielen, wird diese Methode vor onStop () ausgeführt, und es gibt keine Garantie dafür, ob sie vor oder nach onPause () erfolgt.

Steve M.
quelle
1
Vielen Dank. Könnten Sie bitte die Links zur Dokumentation bereitstellen?
Luis Mendo
Los geht's, ich glaube auch nicht, dass zwischen onStart () und onPostCreate () noch etwas anderes ist, also ist onRestoreInstanceState () in der Kette gut definiert.
Steve M
Vielen Dank. Dies klärt das Problem
Luis Mendo
1
@SteveM "Es gibt keine Garantie dafür, ob es vor oder nach onPause () auftritt." Bedeutet dies, dass wir möglicherweise auf NullPointerExceptions stoßen, wenn wir versuchen, auf eine Ansicht zuzugreifen (um einen Wert zum Speichern zu erhalten, z. B. einen Index aus einer Listenansicht)?
Tiago
3
Was wird dann empfohlen, um eine Datenstruktur in onPause zu speichern und stattdessen in onResume in onSaveInstanceState und onRestoreInstanceState wiederherzustellen?
Gödel77
18

Wie pro doc1 und doc2

onSaveInstanceState

Vor Honeycomb wurden Aktivitäten erst nach einer Pause als tötbar angesehen, was bedeutet, dass onSaveInstanceState () unmittelbar vor onPause () aufgerufen wurde. Beginnend mit Honeycomb gelten Aktivitäten jedoch erst dann als tötbar, wenn sie gestoppt wurden. Dies bedeutet, dass onSaveInstanceState () jetzt vor onStop () und nicht unmittelbar vor onPause () aufgerufen wird.

onRestoreInstanceState

Diese Methode wird zwischen onStart () und onPostCreate (Bundle) aufgerufen, wenn die Aktivität aus einem zuvor gespeicherten Zustand neu initialisiert wird

Android-Entwickler
quelle
mochte die Art und Weise, wie Sie Szenarien über verschiedene Android-Versionen beschrieben haben
Jimit Patel
14

Zusätzlich zu den bereits veröffentlichten Antworten wurde in Android P eine subtile Änderung eingeführt:

void onSaveInstanceState (Bundle outState)

Wenn diese Methode aufgerufen wird, wird sie NACH onStop() Anwendungen angewendet, die auf Plattformen abzielen, die mit P beginnen . Für Anwendungen, die auf frühere Plattformversionen abzielen, wird diese Methode vorher ausgeführt, onStop()und es gibt keine Garantie dafür, ob sie vorher oder nachher ausgeführt wird onPause().

Quelle: docs

Hier ist die Antwort, warum diese Änderung eingeführt wird:

... damit eine Anwendung Fragmenttransaktionen sicher ausführen onStop()und später den dauerhaften Status speichern kann.

Quelle: docs

Azizbekian
quelle
Hallo, toller Kommentar. Wissen Sie, wie sich die App verhält, die auf Ziel P abzielt, aber auf einer niedrigeren API ausgeführt wird? Entspricht der App, die auf eine niedrigere API abzielt, oder ist sie über die API hinweg konsistent und behält das Verhalten der "Ausrichtung auf die API" bei?
Filipkowicz
@Filipkowicz, Do you know how will behave app that target P but runs on lower api?Solange die App auf M ausgeführt wird, enthält die Version von Android, die dieses Gerät enthält, keine Änderungen, die in P eingeführt wurden. Dies bedeutet, dass unabhängig davon, ob Sie ein Ziel angegeben haben, dieses nicht angezeigt Pwird anders für Pre-P-Geräte. Hoffe das beantwortet deine Frage.
Azizbekian
Ich fühle mich heute nach dem Lesen dieser Antwort so entspannt, weil ich den androidfreien Kurs über Udacity gemacht habe und sie immer noch die alte Version der Tutorials haben, in der in Lektion 5, Übung 8 angegeben ist, dass die Methoden onStop und onDestroy in der nicht vorhanden sein sollten angezeigte Textansicht. Aber ich wusste nicht, dass dies für die älteren Versionen von Android war und ich führte meine Anwendung auf Android Pie aus und bekam die onStop-Methode in meiner Textansicht. Ich danke dir sehr. Endlich ein gutes Gefühl.
Sandhu
6

Dies ist eine zusätzliche Information für onSaveInstanceState (Bundle)

aus docs

Verwechseln Sie diese Methode nicht mit Rückrufen zum Aktivitätslebenszyklus wie onPause (), die immer aufgerufen werden, wenn eine Aktivität in den Hintergrund gestellt wird oder auf dem Weg zur Zerstörung ist, oder onStop (), das vor der Zerstörung aufgerufen wird. Ein Beispiel für den Aufruf von onPause () und onStop () und nicht für diese Methode ist das Zurücknavigieren eines Benutzers von Aktivität B zu Aktivität A: Es ist nicht erforderlich, onSaveInstanceState (Bundle) für B aufzurufen, da diese bestimmte Instanz niemals wiederhergestellt wird Das System vermeidet es, es aufzurufen. Ein Beispiel für den Aufruf von onPause () und nicht für onSaveInstanceState (Bundle) ist der Start von Aktivität B vor Aktivität A: Das System kann den Aufruf von onSaveInstanceState (Bundle) für Aktivität A vermeiden, wenn es seitdem nicht während der Lebensdauer von B beendet wird Der Status der Benutzeroberfläche von A bleibt erhalten.

Es ist also die Standardimplementierung für ..

Die Standardimplementierung übernimmt für Sie den größten Teil des UI-Status pro Instanz, indem Sie onSaveInstanceState () für jede Ansicht in der Hierarchie mit einer ID aufrufen und die ID der aktuell fokussierten Ansicht speichern (die alle von der wiederhergestellt wird Standardimplementierung von onRestoreInstanceState (Bundle)). Wenn Sie diese Methode überschreiben, um zusätzliche Informationen zu speichern, die nicht von jeder einzelnen Ansicht erfasst werden, möchten Sie wahrscheinlich die Standardimplementierung aufrufen. Andernfalls müssen Sie den gesamten Status jeder Ansicht selbst speichern.

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

// Dieser Rückruf wird nur aufgerufen, wenn eine zuvor mit // onSaveInstanceState () gespeicherte Instanz vorhanden ist. Wir stellen einen Status in onCreate () wieder her, während wir hier optional // einen anderen Status wiederherstellen können, der möglicherweise nach Abschluss von onStart () verwendet werden kann. // Das savedInstanceState-Bundle ist das gleiche wie das in onCreate () verwendete.

@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
quelle
Entschuldigung, wie beantwortet dies die Frage, wann die Save / Restore-Methoden genau aufgerufen werden ?
Luis Mendo