Frage Speichern des Android Activity-Status mit Save Instance State


Ich habe an Android SDK-Plattform gearbeitet, und es ist ein wenig unklar, wie Sie den Status einer Anwendung speichern. Also diese kleine Umrüstung des 'Hello, Android'-Beispiels:

package com.android.hello;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroid extends Activity {

  private TextView mTextView = null;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mTextView = new TextView(this);

    if (savedInstanceState == null) {
       mTextView.setText("Welcome to HelloAndroid!");
    } else {
       mTextView.setText("Welcome back.");
    }

    setContentView(mTextView);
  }
}

Ich dachte, es wäre genug für den einfachsten Fall, aber es antwortet immer mit der ersten Nachricht, egal wie ich von der App weg navigiere.

Ich bin sicher, dass die Lösung so einfach ist wie das Überschreiben onPause oder so ähnlich, aber ich habe 30 Minuten in der Dokumentation herumgestochert und nichts Offensichtliches gefunden.


2234
2017-09-30 04:41


Ursprung


Antworten:


Sie müssen überschreiben onSaveInstanceState(Bundle savedInstanceState) und schreiben Sie die Anwendungsstatuswerte, die Sie ändern möchten, in die Bundle Parameter wie folgt:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
  super.onSaveInstanceState(savedInstanceState);
  // Save UI state changes to the savedInstanceState.
  // This bundle will be passed to onCreate if the process is
  // killed and restarted.
  savedInstanceState.putBoolean("MyBoolean", true);
  savedInstanceState.putDouble("myDouble", 1.9);
  savedInstanceState.putInt("MyInt", 1);
  savedInstanceState.putString("MyString", "Welcome back to Android");
  // etc.
}

Das Bundle ist im Wesentlichen eine Möglichkeit, eine NVP-Karte ("Name-Wert-Paar") zu speichern, und es wird an sie weitergegeben onCreate() und auch onRestoreInstanceState() wo du die Werte so extrahieren würdest:

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
  super.onRestoreInstanceState(savedInstanceState);
  // Restore UI state from the savedInstanceState.
  // This bundle has also been passed to onCreate.
  boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
  double myDouble = savedInstanceState.getDouble("myDouble");
  int myInt = savedInstanceState.getInt("MyInt");
  String myString = savedInstanceState.getString("MyString");
}

Normalerweise würden Sie mit dieser Technik Instanzwerte für Ihre Anwendung speichern (Auswahl, nicht gespeicherter Text usw.).


2271
2017-09-30 06:12



Das savedInstanceState dient nur zum Speichern des Status, der einer aktuellen Instanz einer Aktivität zugeordnet ist, z. B. aktuelle Navigations- oder Auswahlinformationen. Wenn Android eine Aktivität zerstört und neu erstellt, kann sie wieder wie zuvor angezeigt werden. Siehe die Dokumentation für onCreate und onSaveInstanceState

Verwenden Sie für einen langlebigeren Status eine SQLite-Datenbank, eine Datei oder Voreinstellungen. Sehen Speichern des persistenten Zustands.


375
2017-09-30 05:03



Beachten Sie, dass es ist NICHT sicher zu benutzen onSaveInstanceState und onRestoreInstanceState  für persistente Daten, gemäß der Dokumentation über die Aktivität Staaten in http://developer.android.com/reference/android/app/Activity.html.

Das Dokument gibt (im Abschnitt "Activity Lifecycle") Folgendes an:

Beachten Sie, dass das Speichern wichtig ist   persistente Daten in onPause() stattdessen   von onSaveInstanceState(Bundle)   weil das spätere nicht Teil des ist   Lebenszyklus-Callbacks, so wird es nicht sein   in jeder Situation wie beschrieben aufgerufen   in seiner Dokumentation.

Mit anderen Worten, legen Sie Ihren Code zum Speichern / Wiederherstellen für persistente Daten in onPause() und onResume()!

BEARBEITEN: Zur weiteren Klärung, hier ist die onSaveInstanceState() Dokumentation:

Diese Methode wird aufgerufen, bevor eine Aktivität beendet werden kann   Kommt irgendwann in der Zukunft zurück, kann es seinen Zustand wiederherstellen. Zum   Beispiel, wenn die Aktivität B vor der Aktivität A und bei einigen gestartet wird   Punktaktivität A wird getötet, um Ressourcen zurückzufordern, die Aktivität A hat   eine Möglichkeit, den aktuellen Zustand seiner Benutzeroberfläche über diesen zu speichern   Methode, so dass, wenn der Benutzer zu Aktivität A zurückkehrt, der Status von   Benutzerschnittstelle kann über wiederhergestellt werden onCreate(Bundle) oder    onRestoreInstanceState(Bundle).


365
2018-05-25 23:22



Mein Kollege hat einen Artikel geschrieben, in dem der Anwendungsstatus auf Android-Geräten erläutert wird. Er enthält Erläuterungen zu Aktivitätslebenszyklus- und Zustandsinformationen, zum Speichern von Statusinformationen und zum Speichern im Status Bundle und SharedPreferences und Sieh dir das hier an.

Der Artikel behandelt drei Ansätze:

Speichern Sie lokale Variablen- / UI-Steuerdaten für die Anwendungslebensdauer (dh vorübergehend) mit dem Instance State Bundle

[Code sample – Store State in State Bundle]
@Override
public void onSaveInstanceState(Bundle savedInstanceState) 
{
  // Store UI state to the savedInstanceState.
  // This bundle will be passed to onCreate on next call.  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  savedInstanceState.putString(“Name”, strName);
  savedInstanceState.putString(“Email”, strEmail);
  savedInstanceState.putBoolean(“TandC”, blnTandC);

  super.onSaveInstanceState(savedInstanceState);
}

Speichern Sie lokale Variablen- / UI-Steuerdaten zwischen Anwendungsinstanzen (dh permanent) mit gemeinsamen Einstellungen

[Code sample – Store State in SharedPreferences]
@Override
protected void onPause() 
{
  super.onPause();

  // Store values between instances here
  SharedPreferences preferences = getPreferences(MODE_PRIVATE);
  SharedPreferences.Editor editor = preferences.edit();  // Put the values from the UI
  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  editor.putString(“Name”, strName); // value to store
  editor.putString(“Email”, strEmail); // value to store
  editor.putBoolean(“TandC”, blnTandC); // value to store    
  // Commit to storage
  editor.commit();
}

Halten von Objektinstanzen im Arbeitsspeicher zwischen Aktivitäten innerhalb der Anwendungslebensdauer mithilfe von "Nicht beibehaltene Nicht-Konfigurationsinstanz beibehalten"

[Code sample – store object instance]
private cMyClassType moInstanceOfAClass;// Store the instance of an object
@Override
public Object onRetainNonConfigurationInstance() 
{
  if (moInstanceOfAClass != null) // Check that the object exists
      return(moInstanceOfAClass);
  return super.onRetainNonConfigurationInstance();
}

171
2017-08-27 13:54



Dies ist ein klassisches "Gotcha" der Android-Entwicklung. Hier gibt es zwei Probleme:

  • Es gibt einen subtilen Android Framework-Bug, der das Management des Anwendungs-Stacks während der Entwicklung erheblich erschwert, zumindest bei älteren Versionen (nicht ganz sicher, ob / wann / wie es repariert wurde). Ich werde diesen Fehler unten diskutieren.
  • Der "normale" oder beabsichtigte Weg, dieses Problem zu lösen, ist selbst mit der Dualität von onPause / onResume und onSaveInstanceState / onRestoreInstanceState ziemlich kompliziert

Wenn ich all diese Threads durchblättere, vermute ich, dass die meiste Zeit Entwickler über diese beiden verschiedenen Probleme gleichzeitig reden ... daher die ganze Verwirrung und Berichte von "das funktioniert nicht für mich".

Zuerst, um das "beabsichtigte" Verhalten zu klären: onSaveInstance und onRestoreInstance sind zerbrechlich und nur für den Übergangszustand. Die beabsichtigte Verwendung (afaict) ist die Behandlung von Aktivitäten, wenn das Telefon gedreht wird (Orientierungsänderung). Mit anderen Worten, die beabsichtigte Verwendung ist, wenn Ihre Aktivität noch logisch "oben" ist, aber immer noch vom System neu eingerichtet werden muss. Das gespeicherte Bundle wird nicht außerhalb des Prozesses / Arbeitsspeichers / GC gespeichert. Sie können sich also nicht darauf verlassen, wenn Ihre Aktivität in den Hintergrund tritt. Ja, vielleicht wird das Gedächtnis Ihrer Aktivität ihren Weg in den Hintergrund überleben und GC entkommen, aber das ist nicht zuverlässig (noch ist es vorhersehbar).

Wenn Sie also ein Szenario haben, in dem ein sinnvoller "Benutzerfortschritt" oder ein Zustand vorliegt, der zwischen "Starts" Ihrer Anwendung bestehen sollte, sollten Sie onPause und onResume verwenden. Sie müssen einen persistenten Speicher selbst auswählen und vorbereiten.

ABER - es gibt einen sehr verwirrenden Fehler, der all das erschwert. Details sind hier:

http://code.google.com/p/android/issues/detail?id=2373

http://code.google.com/p/android/issues/detail?id=5277

Wenn Ihre Anwendung mit dem Flag SingleTask gestartet wird und Sie sie später über den Startbildschirm oder das Launcher-Menü starten, wird durch diesen nachfolgenden Aufruf eine NEUE Aufgabe erstellt ... Sie haben praktisch zwei verschiedene Instanzen Ihrer App den gleichen Stapel bewohnen ... was sehr schnell sehr merkwürdig wird. Dies scheint zu geschehen, wenn Sie Ihre App während der Entwicklung starten (d. H. Von Eclipse oder Intellij), so dass die Entwickler sehr oft darauf stoßen. Aber auch durch einige der Aktualisierungsmechanismen des App Stores (also auch für Ihre Benutzer).

Ich kämpfte stundenlang durch diese Threads, bis ich erkannte, dass mein Hauptproblem dieser Bug war, nicht das beabsichtigte Framework-Verhalten. Eine tolle Beschreibung und Problemumgehung (UPDATE: siehe unten) scheint von Benutzer @ kaciula in dieser Antwort zu sein:

Home-Taste drücken Verhalten

UPDATE Juni 2013: Monate später habe ich endlich die "richtige" Lösung gefunden. Sie müssen selbst keine statusbehafteten stagedApp-Flags verwalten, Sie können dies aus dem Framework erkennen und entsprechend bailen. Ich benutze dies am Anfang meiner LauncherActivity.onCreate:

if (!isTaskRoot()) {
    Intent intent = getIntent();
    String action = intent.getAction();
    if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && action != null && action.equals(Intent.ACTION_MAIN)) {
        finish();
        return;
    }
}

126
2017-10-19 23:47



onSaveInstanceStatewird aufgerufen, wenn das System Speicher benötigt und eine Anwendung beendet. Es wird nicht aufgerufen, wenn der Benutzer die Anwendung gerade schließt. Ich denke also, dass auch der Anwendungsstatus gespeichert werden sollte onPause Es sollte in einem dauerhaften Speicher wie gespeichert werden Preferences oder Sqlite


70
2018-05-07 00:21



Beide Methoden sind nützlich und gültig und beide sind am besten für verschiedene Szenarien geeignet:

  1. Der Benutzer beendet die Anwendung und öffnet sie zu einem späteren Zeitpunkt erneut, aber die Anwendung muss die Daten der letzten Sitzung erneut laden. Dies erfordert einen Ansatz für eine dauerhafte Speicherung, z. B. die Verwendung von SQLite.
  2. Der Benutzer wechselt zur Anwendung und kehrt dann zum Original zurück und möchte dort weitermachen, wo er aufgehört hat - Speichern und Wiederherstellen von Paketdaten (z. B. Anwendungsstatusdaten) in onSaveInstanceState() und onRestoreInstanceState() ist in der Regel ausreichend.

Wenn Sie die Zustandsdaten dauerhaft speichern, können Sie sie erneut in einem laden onResume() oder onCreate() (oder tatsächlich bei jedem Lifecycle-Anruf). Dies kann oder kann nicht das gewünschte Verhalten sein. Wenn Sie es in einem Bündel in einem speichern InstanceState, dann ist es vorübergehend und eignet sich nur zum Speichern von Daten für die Verwendung in der Sitzung desselben Benutzers (ich verwende den Begriff Sitzung lose), aber nicht zwischen "Sitzungen".

Es ist nicht so, dass ein Ansatz besser ist als der andere, wie alles, es ist nur wichtig zu verstehen, welches Verhalten Sie benötigen und den am besten geeigneten Ansatz auszuwählen.


59
2018-06-27 16:17



Der Rettungszustand ist für mich bestenfalls ein Kludscher. Wenn Sie persistente Daten speichern müssen, verwenden Sie einfach ein SQLite Datenbank. Android macht es SOOO einfach.

Etwas wie das:

import java.util.Date;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class dataHelper {

    private static final String DATABASE_NAME = "autoMate.db";
    private static final int DATABASE_VERSION = 1;

    private Context context;
    private SQLiteDatabase db;
    private OpenHelper oh ;

    public dataHelper(Context context) {
        this.context = context;
        this.oh = new OpenHelper(this.context);
        this.db = oh.getWritableDatabase();
    }

    public void close()
    {
        db.close();
        oh.close();
        db = null;
        oh = null;
        SQLiteDatabase.releaseMemory();
    }


    public void setCode(String codeName, Object codeValue, String codeDataType)
    {
        Cursor codeRow = db.rawQuery("SELECT * FROM code WHERE codeName = '"+  codeName + "'", null);
        String cv = "" ;

        if (codeDataType.toLowerCase().trim().equals("long") == true)
        {
            cv = String.valueOf(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("int") == true)
        {
            cv = String.valueOf(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("date") == true)
        {
            cv = String.valueOf(((Date)codeValue).getTime());
        }
        else if (codeDataType.toLowerCase().trim().equals("boolean") == true)
        {
            String.valueOf(codeValue);
        }
        else
        {
            cv = String.valueOf(codeValue);
        }

        if(codeRow.getCount() > 0) //exists-- update
        {
            db.execSQL("update code set codeValue = '" + cv +
                "' where codeName = '" + codeName + "'");
        }
        else // does not exist, insert
        {
            db.execSQL("INSERT INTO code (codeName, codeValue, codeDataType) VALUES(" +
                    "'" + codeName + "'," +
                    "'" + cv + "'," +
                    "'" + codeDataType + "')" );
        }
    }

    public Object getCode(String codeName, Object defaultValue)
    {
        //Check to see if it already exists
        String codeValue = "";
        String codeDataType = "";
        boolean found = false;
        Cursor codeRow  = db.rawQuery("SELECT * FROM code WHERE codeName = '"+  codeName + "'", null);
        if (codeRow.moveToFirst())
        {
            codeValue = codeRow.getString(codeRow.getColumnIndex("codeValue"));
            codeDataType = codeRow.getString(codeRow.getColumnIndex("codeDataType"));
            found = true;
        }

        if (found == false)
        {
            return defaultValue;
        }
        else if (codeDataType.toLowerCase().trim().equals("long") == true)
        {
            if (codeValue.equals("") == true)
            {
                return (long)0;
            }
            return Long.parseLong(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("int") == true)
        {
            if (codeValue.equals("") == true)
            {
                return (int)0;
            }
            return Integer.parseInt(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("date") == true)
        {
            if (codeValue.equals("") == true)
            {
                return null;
            }
            return new Date(Long.parseLong(codeValue));
        }
        else if (codeDataType.toLowerCase().trim().equals("boolean") == true)
        {
            if (codeValue.equals("") == true)
            {
                return false;
            }
            return Boolean.parseBoolean(codeValue);
        }
        else
        {
            return (String)codeValue;
        }
    }


    private static class OpenHelper extends SQLiteOpenHelper {

        OpenHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("CREATE TABLE IF  NOT EXISTS code" +
            "(id INTEGER PRIMARY KEY, codeName TEXT, codeValue TEXT, codeDataType TEXT)");
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }
    }
}

Ein einfacher Anruf danach

dataHelper dh = new dataHelper(getBaseContext());
String status = (String) dh.getCode("appState", "safetyDisabled");
Date serviceStart = (Date) dh.getCode("serviceStartTime", null);
dh.close();
dh = null;

50
2018-06-23 17:07



Ich denke, ich habe die Antwort gefunden. Lass mich erzählen, was ich mit einfachen Worten getan habe:

Angenommen, ich habe zwei Aktivitäten, activity1 und activity2, und ich navigiere von activity1 zu activity2 (ich habe einige Arbeiten in activity2 gemacht) und wieder zurück zu activity1, indem ich auf eine Schaltfläche in activity1 klicke. Jetzt wollte ich zu activity2 zurückkehren und möchte meine activity2 in der gleichen Bedingung sehen, als ich activity2 das letzte Mal verlassen habe.

Für das obige Szenario habe ich im Manifest einige Änderungen wie folgt vorgenommen:

<activity android:name=".activity2"
          android:alwaysRetainTaskState="true"      
          android:launchMode="singleInstance">
</activity>

Und in der Aktivität1 auf dem Button Click Event habe ich das so gemacht:

Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.setClassName(this,"com.mainscreen.activity2");
startActivity(intent);

Und in activity2 on button click event habe ich folgendes gemacht:

Intent intent=new Intent();
intent.setClassName(this,"com.mainscreen.activity1");
startActivity(intent);

Was nun passiert, ist, dass die Änderungen, die wir in der Aktivität2 vorgenommen haben, nicht verloren gehen, und wir können activity2 in dem Zustand sehen, in dem wir zuvor gegangen sind.

Ich glaube, das ist die Antwort und das funktioniert gut für mich. Korrigiere mich, wenn ich falsch liege.


50
2018-02-05 11:35



onSaveInstanceState() für transiente Daten (wiederhergestellt in onCreate()/onRestoreInstanceState()), onPause() für persistente Daten (wiederhergestellt in onResume()). Von technischen Android-Ressourcen:

onSaveInstanceState () wird von Android aufgerufen, wenn die Aktivität gestoppt wird und möglicherweise beendet wird, bevor sie fortgesetzt wird! Das bedeutet, dass alle Zustände gespeichert werden sollten, die erforderlich sind, um beim Neustart der Aktivität wieder in die gleiche Bedingung zu gelangen. Es ist das Gegenstück zur onCreate () -Methode, und tatsächlich ist das in onCreate () übergebene savedInstanceState-Bundle dasselbe Bündel, das Sie in der onSaveInstanceState () -Methode als outState konstruiert haben.

onPause () und auf Wiederaufnahme() sind auch komplementäre Methoden. onPause () wird immer dann aufgerufen, wenn die Aktivität endet, auch wenn wir dies eingeleitet haben (z. B. mit einem finish () -Aufruf). Wir werden dies verwenden, um die aktuelle Notiz in der Datenbank zu speichern. Es empfiehlt sich, alle Ressourcen freizugeben, die auch während einer onPause () freigegeben werden können, um im passiven Zustand weniger Ressourcen zu belegen.


36
2018-01-17 18:28



Eine Aktivität neu erstellen

Es gibt ein paar Szenarien, in denen Ihre Aktivität aufgrund des normalen Anwendungsverhaltens zerstört wird, z. B. wenn der Benutzer die Zurück-Schaltfläche drückt oder Ihre Aktivität durch Aufruf eine eigene Zerstörung signalisiert finish(). Das System kann auch Ihre Aktivität zerstören, wenn es momentan gestoppt ist und seit langer Zeit nicht mehr verwendet wird oder die Vordergrundaktivität mehr Ressourcen benötigt, so dass das System Hintergrundprozesse herunterfahren muss, um Speicher wiederherzustellen.

Wenn dein activity wird zerstört, weil der Benutzer Zurück oder die drückt activity beendet sich selbst, das Konzept des Systems davon Activity Instanz ist für immer weg, weil das Verhalten anzeigt, dass die Aktivität nicht länger benötigt wird. Wenn das System jedoch die Aktivität aufgrund von Systemeinschränkungen (und nicht aufgrund des normalen Anwendungsverhaltens) zerstört, merkt sich das System, obwohl es tatsächlich existierte, dass es existierte, so dass das System, wenn der Benutzer dorthin zurück navigiert, ein neues erstellt Instanz der Aktivität, die eine Gruppe gespeicherter Daten verwendet, die den Status der Aktivität beschreiben, als sie war destroyed. Die gespeicherten Daten, die das System zum Wiederherstellen des vorherigen Status verwendet, werden als "Instanzstatus" bezeichnet und sind eine Sammlung von Schlüssel / Wert-Paaren, die in einem Bundle-Objekt gespeichert sind.

Um zusätzliche Daten zum Aktivitätsstatus zu speichern, müssen Sie die Call-Methode onSaveInstanceState () überschreiben. Das System ruft diese Methode auf, wenn der Benutzer Ihre Aktivität verlässt und das Bundle-Objekt übergibt, das für den Fall gespeichert wird, dass Ihre Aktivität unerwartet zerstört wird. Wenn das System die Aktivitätsinstanz später erneut erstellen muss, übergibt es das gleiche Bundle-Objekt an beide onRestoreInstanceState() und onCreate() Methoden. enter image description here

Wenn das System Ihre Aktivität stoppt, ruft es an onSaveInstanceState() (1) Sie können also zusätzliche Statusdaten angeben, die Sie speichern möchten, falls die Activity-Instanz neu erstellt werden muss. Wenn die Aktivität zerstört wird und dieselbe Instanz neu erstellt werden muss, übergibt das System die unter (1) definierten Statusdaten an beide onCreate() Methode (2) und die onRestoreInstanceState() Methode (3).

Speichern Sie Ihre Activity Zustand

Wenn Ihre Aktivität zu stoppen beginnt, ruft das System auf onSaveInstanceState() Ihre Aktivität kann also Statusinformationen mit einer Sammlung von Schlüssel / Wert-Paaren speichern. Die Standardimplementierung dieser Methode speichert Informationen über den Status der Ansichtshierarchie der Aktivität, z. B. den Text in einer EditText Widget oder die Bildlaufposition von a ListView.

Um zusätzliche Statusinformationen für Ihre Aktivität zu speichern, müssen Sie Folgendes implementieren onSaveInstanceState() und fügen Schlüssel-Wert-Paare dem Bündel-Objekt hinzu. Beispielsweise:

  static final String STATE_SCORE = "playerScore";
  static final String STATE_LEVEL = "playerLevel";

  @Override
  public void onSaveInstanceState(Bundle savedInstanceState) {
  // Save the user's current game state
  savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
  savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);

  // Always call the superclass so it can save the view hierarchy state
  super.onSaveInstanceState(savedInstanceState);
}

Achtung: Rufen Sie immer die Superklassenimplementierung von onSaveInstanceState()Daher kann die Standardimplementierung den Status der Ansichtshierarchie speichern.

Wiederherstellen Activity Zustand

Wenn Ihre Aktivität wiederhergestellt wird, nachdem sie zuvor zerstört wurde, können Sie den gespeicherten Status aus dem Bundle wiederherstellen, an dem das System Ihre Aktivität weitergibt. Beide onCreate() und onRestoreInstanceState() Callback-Methoden erhalten das gleiche Bundle enthält die Instanzstatusinformationen.

Weil das onCreate() Methode wird aufgerufen, ob das System eine neue Instanz Ihrer Aktivität erstellt oder eine vorherige neu erstellt. Sie müssen überprüfen, ob der Status Bundle null ist, bevor Sie versuchen, sie zu lesen. Wenn es null ist, erstellt das System eine neue Instanz der Aktivität, anstatt eine vorherige Instanz wiederherzustellen, die zerstört wurde.

Zum Beispiel können Sie hier einige Zustandsdaten wiederherstellen onCreate():

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState); // Always call the superclass first

 // Check whether we're recreating a previously destroyed instance
 if (savedInstanceState != null) {
    // Restore value of members from saved state
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
 } else {
    // Probably initialize members with default values for a new instance
 }

 }

Anstatt den Status während wiederherzustellen onCreate() Sie können wählen, zu implementieren onRestoreInstanceState(), die das System nach der onStart() Methode. Das System ruft auf onRestoreInstanceState() Nur wenn ein gespeicherter Status wiederhergestellt wird, müssen Sie nicht überprüfen, ob das Bundle null ist:

  public void onRestoreInstanceState(Bundle savedInstanceState) {
  // Always call the superclass so it can restore the view hierarchy
  super.onRestoreInstanceState(savedInstanceState);

  // Restore state members from saved instance
  mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
  mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

36
2018-04-15 04:13