web-dev-qa-db-de.com

onSaveInstanceState () und onRestoreInstanceState ()

Ich versuche, den Zustand einer Activity mit den Methoden onSaveInstanceState() und onRestoreInstanceState() zu speichern und wiederherzustellen.

Das Problem ist, dass es niemals die onRestoreInstanceState()-Methode betritt. Kann mir jemand erklären, warum das so ist?

131
BlaBRA

Normalerweise stellen Sie Ihren Zustand in onCreate() wieder her. Es ist möglich, es auch in onRestoreInstanceState() wiederherzustellen, aber nicht sehr häufig. (onRestoreInstanceState() wird nach onStart() aufgerufen, wohingegen onCreate() vor onStart() aufgerufen wird.

Verwenden Sie die put-Methoden, um Werte in onSaveInstanceState() zu speichern:

protected void onSaveInstanceState(Bundle icicle) {
  super.onSaveInstanceState(icicle);
  icicle.putLong("param", value);
}

Und stellen Sie die Werte in onCreate() wieder her:

public void onCreate(Bundle icicle) {
  if (icicle != null){
    value = icicle.getLong("param");
  }
}

Sie müssen Ansichtszustände nicht speichern, da sie gespeichert werden automatisch durch Aufruf von super.onSaveInstanceState (icicle) ;.

184
Robert

onRestoreInstanceState() wird nur beim Wiederherstellen Aktivität genannt, nachdem sie vom Betriebssystem getötet war. Eine solche Situation tritt auf, wenn:

  • ausrichtung des Geräts ändert sich (Ihre Aktivität wird zerstört und neu erstellt)
  • vor Ihnen liegt eine weitere Aktivität, und irgendwann bricht das Betriebssystem Ihre Aktivität ab, um beispielsweise Speicherplatz freizugeben. Wenn Sie das nächste Mal mit Ihrer Aktivität beginnen, wird onRestoreInstanceState() aufgerufen.

Im Gegensatz dazu: Wenn Sie sich in Ihrer Aktivität befinden und die Back-Taste auf dem Gerät drücken, wird Ihre Aktivität beendet () (dh, denken Sie an das Beenden der Desktop-Anwendung) und das nächste Mal, wenn Sie Ihre App starten, wird sie "frisch" gestartet, dh ohne gespeichertem Status, da Sie ihn absichtlich verlassen haben, wenn Sie Back drücken.

Eine andere Quelle der Verwirrung ist, dass onSaveInstanceState() aufgerufen wird, wenn eine App den Fokus auf eine andere App verliert, aber wenn Sie zurück zu Ihrer App navigieren, onRestoreInstanceState() möglicherweise nicht aufgerufen wird. Dies ist der Fall, der in der ursprünglichen Frage beschrieben wurde, d. H., Wenn Ihre Aktivität NICHT in der Zeit abgebrochen wurde, in der eine andere Aktivität im Vordergrund stand, wird onRestoreInstanceState() NICHT aufgerufen, da Ihre Aktivität ziemlich "lebendig" ist.

Alles in allem, wie in der Dokumentation zu onRestoreInstanceState() angegeben:

Die meisten Implementierungen verwenden einfach onCreate (Bundle), um ihre .__ wiederherzustellen. state, aber es ist manchmal praktisch, es hier nach all der .__ zu tun. Initialisierung wurde durchgeführt, oder um Unterklassen zu erlauben zu entscheiden, ob um Ihre Standardimplementierung zu verwenden. Die Standardimplementierung dieses Die Methode führt eine Wiederherstellung aller Ansichtszustände durch, die zuvor .__ waren. von onSaveInstanceState (Bundle) eingefroren.

Ich habe es gelesen: Es gibt keinen Grund, onRestoreInstanceState() zu überschreiben, es sei denn, Sie verwenden Activity und es wird erwartet, dass jemand Ihre Unterklasse subclassiert. 

146
Ognyan

Der Zustand, den Sie unter onSaveInstanceState() speichern, ist später beim Aufruf der onCreate()-Methode verfügbar. Verwenden Sie also onCreate (und dessen Parameter Bundle), um den Status Ihrer Aktivität wiederherzustellen.

7

Um dieses Problem zu umgehen, können Sie ein Paket mit den Daten, die Sie verwalten möchten, in der Absicht speichern, die Sie zum Starten von Aktivität A verwenden.

Intent intent = new Intent(this, ActivityA.class);
intent.putExtra("bundle", theBundledData);
startActivity(intent);

Aktivität A müsste dies an Aktivität B zurückgeben. Sie würden die Absicht in der onCreate-Methode von Aktivität B abrufen.

Intent intent = getIntent();
Bundle intentBundle;
if (intent != null)
    intentBundle = intent.getBundleExtra("bundle");
// Do something with the data.

Eine andere Idee ist, eine Repository-Klasse zu erstellen, um den Aktivitätsstatus zu speichern und jede Ihrer Aktivitäten auf diese Klasse verweisen zu lassen (möglicherweise mithilfe einer Singleton-Struktur.).

4
sotrh

Ich habe festgestellt, dass onSaveInstanceState immer aufgerufen wird, wenn eine andere Aktivität in den Vordergrund tritt. Und so ist onStop.

OnRestoreInstanceState wurde jedoch nur aufgerufen, wenn auch onCreate und onStart aufgerufen wurden. OnCreate und onStart wurden NICHT immer aufgerufen.

Es scheint also, als würde Android die Statusinformationen nicht immer löschen, auch wenn die Aktivität in den Hintergrund rückt. Es ruft jedoch die Lebenszyklusmethoden auf, um den Status zu speichern, nur um sicher zu sein. Wenn der Status nicht gelöscht wird, ruft Android die Lebenszyklusmethoden nicht zum Wiederherstellen des Status auf, da sie nicht benötigt werden.

Abbildung 2 beschreibt dies.

3
buzz

Hauptsache, wenn Sie nicht in onSaveInstanceState() speichern, wird onRestoreInstanceState() nicht aufgerufen. Dies ist der Hauptunterschied zwischen restoreInstanceState() und onCreate(). Stellen Sie sicher, dass Sie wirklich etwas speichern. Am wahrscheinlichsten ist dies dein Problem.

3
user1771286

Ich denke, dass dieser Thread ziemlich alt war. Ich erwähne nur einen anderen Fall, dass onSaveInstanceState() auch aufgerufen wird, wenn Sie Activity.moveTaskToBack(boolean nonRootActivity) aufrufen. 

2
macio.Jun

Wenn Sie Orientierungsänderungen der Aktivität mit Android:configChanges="orientation|screenSize" und onConfigurationChanged(Configuration newConfig) bearbeiten, wird onRestoreInstanceState() nicht aufgerufen.

1
Rajkiran

Es ist nicht erforderlich, dass onRestoreInstanceState immer nach onSaveInstanceState aufgerufen wird.

Beachten Sie Folgendes: OnRestoreInstanceState wird immer aufgerufen, wenn die Aktivität gedreht wird (wenn die Ausrichtung nicht behandelt wird) oder Ihre Aktivität geöffnet wird und andere Apps geöffnet werden, sodass Ihre Aktivitätsinstanz vom Betriebssystem aus dem Speicher gelöscht wird.

1

Ich kann das so machen (sorry, es ist zwar kein Java, aber kein Problem ...):

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

UND IN IHRER AKTIVITÄT ZUR ERGEBNIS

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();

}

ENDLICH

protected override void OnActivityResult(int iRequestCode, Android.App.Result oResultCode, Intent oIntent)
{
base.OnActivityResult (iRequestCode, oResultCode, oIntent);
iValue = oIntent.Extras.GetInt("MYVALUE", -1); //=> 1234567890
}
0
EDynamic90

Ich bin nur darauf gestoßen und habe gemerkt, dass die Dokumentation meine Antwort hatte:

"Diese Funktion wird niemals mit einem Nullstatus aufgerufen."

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

In meinem Fall habe ich mich gefragt, warum der onRestoreInstanceState bei der ersten Instantiierung nicht aufgerufen wurde. Dies bedeutet auch, wenn Sie nichts speichern, wird es nicht aufgerufen, wenn Sie Ihre Ansicht rekonstruieren.

0
Ben Scannell

In meinem Fall wurde onRestoreInstanceState aufgerufen, als die Aktivität nach Änderung der Geräteorientierung rekonstruiert wurde. onCreate(Bundle) wurde zuerst aufgerufen, aber das Bündel hatte nicht die Schlüssel/Werte, die ich mit onSaveInstanceState(Bundle) eingestellt habe. 

Gleich danach wurde onRestoreInstanceState(Bundle) mit einem Bundle aufgerufen, das die richtigen Schlüssel/Werte hatte.

0
elvitucho