wischen - Speichern des Status der Android-Aktivität mithilfe des Status der Instanz speichern




inflater inflate erklärung (18)

Hinzufügen von LiveData (Android-Architekturkomponenten) zu Ihrem Projekt

Fügen Sie die folgende Abhängigkeit hinzu

implementation "android.arch.lifecycle:extensions:1.1.0"

LiveData nimmt einen Beobachter auf und benachrichtigt ihn nur dann, wenn sich die Daten im Status STARTED oder RESUMED befinden. Der Vorteil von LiveData besteht darin, dass die Aktivität onChanged für den Beobachter nicht aufgerufen wird, wenn Ihre Aktivität in einen anderen Status als STARTED oder RESUMED wechselt .

private TextView mTextView;
private MutableLiveData<String> mMutableLiveData;

@Override
protected void onCreate(Bundle savedInstanceState) {
    mTextView = (TextView) findViewById(R.id.textView);
    mMutableLiveData = new MutableLiveData<>();
    mMutableLiveData.observe(this, new Observer<String>() {
        @Override
        public void onChanged(@Nullable String s) {
            mTextView.setText(s);
        }
    });

}

https://code.i-harness.com

Ich habe an einer Android SDK-Plattform gearbeitet, und es ist ein wenig unklar, wie der Status einer Anwendung gespeichert wird. In Anbetracht dieser kleinen Umrüstung des Beispiels "Hallo, Android":

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 für den einfachsten Fall ausreichend, aber es antwortet immer mit der ersten Nachricht, egal wie ich von der App weg navigiere.

Ich bin mir sicher, dass die Lösung so einfach ist, wie onPause oder ähnliches zu überschreiben, aber ich habe mich seit onPause 30 Minuten in der Dokumentation onPause und nichts offensichtliches gefunden.


Beachten Sie, dass die Verwendung von onSaveInstanceState und onRestoreInstanceState für persistente Daten NICHT sicher ist, wie in der Dokumentation zu Aktivitätsstatus in developer.android.com/reference/android/app/Activity.html .

Das Dokument gibt an (im Abschnitt "Aktivitätslebenszyklus"):

Beachten Sie, dass es wichtig ist, persistente Daten in onPause() anstelle von onSaveInstanceState(Bundle) zu speichern, da die späteren nicht Teil der Lifecycle-Callbacks sind und daher nicht in jeder Situation aufgerufen werden, wie in der Dokumentation beschrieben.

Mit anderen Worten, setzen Sie Ihren Speicher- / Wiederherstellungscode für persistente Daten in onPause() und onResume() !

BEARBEITEN : Zur weiteren Verdeutlichung die Dokumentation zu onSaveInstanceState() :

Diese Methode wird aufgerufen, bevor eine Aktivität abgebrochen wird, damit sie ihren Status wiederherstellen kann, wenn sie in der Zukunft zurückkehrt. Wenn beispielsweise Aktivität B vor Aktivität A gestartet wird und Aktivität A zu einem bestimmten Zeitpunkt beendet wird, um Ressourcen zurückzugewinnen, hat Aktivität A die Möglichkeit, den aktuellen Status der Benutzeroberfläche über diese Methode zu speichern, wenn der Benutzer zurückkehrt In Aktivität A kann der Zustand der Benutzeroberfläche über onCreate(Bundle) oder onRestoreInstanceState(Bundle) wiederhergestellt werden.


Der savedInstanceState dient nur zum Speichern des Zustands, der einer aktuellen Instanz einer Aktivität zugeordnet ist, z. B. der aktuellen Navigation oder Auswahlinformationen. Wenn also Android eine Aktivität zerstört und neu erstellt, kann sie wie zuvor wiederhergestellt werden. Weitere onCreate Sie in der Dokumentation zu onCreate und onSaveInstanceState

Für eine längere Lebensdauer sollten Sie die Verwendung einer SQLite-Datenbank, einer Datei oder von Voreinstellungen in Betracht ziehen. Siehe Dauerzustand speichern .


Dies ist eine klassische "Gotcha" der Android-Entwicklung. Hier gibt es zwei Probleme:

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

Beim Durchstöbern all dieser Threads vermute ich, dass Entwickler in den meisten Fällen gleichzeitig über diese zwei verschiedenen Themen sprechen ... daher all die Verwirrung und Berichte über "das funktioniert nicht für mich".

Erstens, um das "beabsichtigte" Verhalten zu klären: onSaveInstance und onRestoreInstance sind fragil und nur für einen vorübergehenden Zustand. Die beabsichtigte Verwendung (Affekt) ist die Durchführung der Aktivitätserholung, wenn das Telefon gedreht wird (Ausrichtungsänderung). Mit anderen Worten, die beabsichtigte Verwendung liegt vor, wenn Ihre Aktivität immer noch logisch "oben" ist, jedoch vom System erneut bestätigt werden muss. Das gespeicherte Bundle wird nicht außerhalb des Prozesses / Speichers / GC gespeichert. Sie können sich also nicht wirklich darauf verlassen, wenn Ihre Aktivitäten in den Hintergrund treten. Ja, vielleicht überlebt der Speicher Ihrer Aktivität die Reise in den Hintergrund und entgeht der GC, aber dies ist nicht zuverlässig (und auch nicht vorhersehbar).

Wenn Sie also ein Szenario haben, in dem sinnvolle "Benutzerfortschritte" oder Zustände bestehen, die zwischen den "Startvorgängen" Ihrer Anwendung bestehen bleiben sollen, sollten Sie onPause und onResume verwenden. Sie müssen selbst einen dauerhaften Speicher auswählen und vorbereiten.

ABER - es gibt einen sehr verwirrenden Fehler, der all dies kompliziert. Details finden Sie 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 SingleTask-Flag gestartet wird und Sie sie später über den Startbildschirm oder das Startmenü starten, wird durch den folgenden Aufruf eine NEUE Aufgabe erstellt ... Sie haben praktisch zwei verschiedene Instanzen Ihrer App den gleichen Stack bewohnen ... was sehr schnell sehr seltsam wird. Dies scheint zu passieren, wenn Sie Ihre App während der Entwicklung starten (z. B. von Eclipse oder Intellij). Daher stoßen Entwickler viel darauf. Aber auch durch einige der App Store-Aktualisierungsmechanismen (so wirkt sich dies auch auf Ihre Benutzer aus).

Ich habe mich stundenlang durch diese Threads gekämpft, bevor mir klar wurde, dass mein Hauptaugenmerk auf diesen Fehler und nicht auf das beabsichtigte Rahmenverhalten gerichtet war. Eine tolle Kritik und Problemumgehung (UPDATE: siehe unten) scheint in dieser Antwort von Benutzer @kaciula zu stammen:

Home Tastendruck Verhalten

UPDATE Juni 2013 : Monate später habe ich endlich die 'richtige' Lösung gefunden. Sie müssen keine stateful-startApp-Flags selbst verwalten, Sie können dies aus dem Framework herausfinden und entsprechend entlassen. Ich verwende 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;
    }
}

Mein Kollege schrieb einen Artikel, in dem der Anwendungsstatus auf Android-Geräten erläutert wird, einschließlich Erklärungen zu Aktivitätslebenszyklus und SharedPreferences , zum Speichern von SharedPreferences sowie zum Speichern in State Bundle und SharedPreferences Sie einen Blick darauf werfen .

Der Artikel behandelt drei Ansätze:

Speichern Sie mit Hilfe des Instance State Bundle lokale varible / UI-Steuerungsdaten für die Anwendungslebensdauer (dh vorübergehend)

[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 variable / UI-Steuerungsdaten zwischen Anwendungsinstanzen (dh dauerhaft) mithilfe der gemeinsamen Voreinstellungen

[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 zwischen Aktivitäten innerhalb der Anwendungslebensdauer mithilfe der Instanz "Nicht beibehaltene Konfiguration" erhalten

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

Sie müssen onSaveInstanceState(Bundle savedInstanceState) und die Werte für die Anwendungsstatus, die Sie ändern möchten, in den Bundle Parameter wie onSaveInstanceState(Bundle savedInstanceState) schreiben:

@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 Methode zum Speichern einer NVP-Karte ("Name-Value Pair") und wird an onCreate() und auch onRestoreInstanceState() wo Sie die Werte wie onRestoreInstanceState() extrahieren würden:

@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 verwenden Sie diese Technik, um Instanzwerte für Ihre Anwendung zu speichern (Auswahl, nicht gespeicherter Text usw.).


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

onSaveInstanceState () wird von Android aufgerufen, wenn die Aktivität gestoppt wird, und möglicherweise beendet, bevor sie fortgesetzt wird! Das heißt, es sollte alle erforderlichen Zustände speichern, die erforderlich sind, um beim Neustart der Aktivität den gleichen Zustand wiederherzustellen. Es ist das Gegenstück zur onCreate () -Methode. Tatsächlich ist das gespeicherteInstanceState-Bundle, das an onCreate () übergeben wurde, dasselbe Bundle, das Sie als outState in der onSaveInstanceState () -Methode erstellen.

onPause () und onResume () sind ebenfalls komplementäre Methoden. onPause () wird immer dann aufgerufen, wenn die Aktivität endet, selbst wenn wir (beispielsweise mit einem finish () - Aufruf) diesen Aufruf initiiert haben. Wir werden dies verwenden, um die aktuelle Notiz in der Datenbank zu speichern. Es empfiehlt sich, alle Ressourcen freizugeben, die während einer onPause () -Eigenschaft freigegeben werden können, um im passiven Zustand weniger Ressourcen zu beanspruchen.


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


Es gibt grundsätzlich zwei Möglichkeiten, diese Änderung umzusetzen.

  1. mit onSaveInstanceState()und onRestoreInstanceState().
  2. In manifestieren android:configChanges="orientation|screenSize".

Ich empfehle wirklich nicht, die zweite Methode zu verwenden. Denn in einer meiner Erfahrungen verursachte es, dass die Hälfte des Bildschirms schwarz wurde, während er vom Hochformat in das Querformat und umgekehrt gedreht wurde.

Mit der ersten oben genannten Methode können wir Daten beibehalten, wenn sich die Ausrichtung ändert oder eine Konfigurationsänderung erfolgt. Ich kenne einen Weg, auf dem Sie jede Art von Daten innerhalb des Zustandsobjekts „SavedInstance“ speichern können.

Beispiel: Betrachten Sie einen Fall, wenn Sie ein Json-Objekt beibehalten möchten. Erstellen Sie eine Modellklasse mit Gettern und Setters.

class MyModel extends Serializable{
JSONObject obj;

setJsonObject(JsonObject obj)
{
this.obj=obj;
}

JSONObject getJsonObject()
return this.obj;
} 
}

Führen Sie nun in Ihrer Aktivität in der Methode onCreate und der Methode OnSaveInstanceState Folgendes aus. Es wird ungefähr so ​​aussehen:

@override
onCreate(Bundle savedInstaceState){
MyModel data= (MyModel)savedInstaceState.getSerializable("yourkey")
JSONObject obj=data.getJsonObject();
//Here you have retained JSONObject and can use.
}


@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//Obj is some json object 
MyModel dataToSave= new MyModel();
dataToSave.setJsonObject(obj);
oustate.putSerializable("yourkey",dataToSave); 

}

Kotlin-Code:

sparen:

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState.apply {
        putInt("intKey", 1)
        putString("stringKey", "String Value")
        putParcelable("parcelableKey", parcelableObject)
    })
}

und dann in onCreate()oderonRestoreInstanceState()

    val restoredInt = savedInstanceState?.getInt("intKey") ?: 1 //default int
    val restoredString = savedInstanceState?.getString("stringKey") ?: "default string"
    val restoredParcelable = savedInstanceState?.getParcelable<ParcelableClass>("parcelableKey") ?: ParcelableClass() //default parcelable

Fügen Sie Standardwerte hinzu, wenn Sie keine Optionals verwenden möchten


Wenn eine Aktivität erstellt wird, wird die onCreate () -Methode aufgerufen.

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

savedInstanceState ist ein Objekt der Bundle-Klasse, das zum ersten Mal null ist, aber Werte enthält, wenn es neu erstellt wird. Um den Status der Aktivität zu speichern, müssen Sie onSaveInstanceState () überschreiben.

   @Override
    protected void onSaveInstanceState(Bundle outState) {
      outState.putString("key","Welcome Back")
        super.onSaveInstanceState(outState);       //save state
    }

Setzen Sie Ihre Werte in "outState" -Objekt wie "outState.putString" ("key", "Welcome Back") und speichern Sie sie, indem Sie super aufrufen. Wenn die Aktivität zerstört wird, wird der Status im Bundle-Objekt gespeichert und kann nach der Wiederherstellung in onCreate () oder onRestoreInstanceState () wiederhergestellt werden. Bündel, die in onCreate () und onRestoreInstanceState () empfangen wurden, sind identisch.

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

          //restore activity's state
         if(savedInstanceState!=null){
          String reStoredString=savedInstanceState.getString("key");
            }
    }

oder

  //restores activity's saved state
 @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
      String restoredMessage=savedInstanceState.getString("key");
    }

onSaveInstanceStatus wirklich angeben, wenn die Aktivität in den Hintergrund wechselt

Zitat aus den Dokumenten: "Die Methode onSaveInstanceState(Bundle)wird aufgerufen, bevor die Aktivität in einen solchen Hintergrundzustand versetzt wird"


Hier ist ein Kommentar von Steve Moseleys Antwort (von ToolmakerSteve ), der die Dinge in die richtige Perspektive bringt (im ganzen onSaveInstanceState vs. onPause, Ostkosten vs. Westkostensaga)

@VVK - Ich stimme teilweise nicht zu. Einige Methoden zum Beenden einer App lösen keinen onSaveInstanceState (oSIS) aus. Dies begrenzt den Nutzen von oSIS. Es lohnt sich zu unterstützen, für minimale Betriebssystemressourcen. Wenn eine App jedoch den Benutzer in den Status zurückversetzen möchte, in dem er sich befand, unabhängig davon, wie die App beendet wurde, muss stattdessen ein permanenter Speicheransatz verwendet werden. Ich verwende onCreate, um nach Bundle zu suchen. Wenn es fehlt, überprüfe ich den permanenten Speicher. Dies zentralisiert die Entscheidungsfindung. Ich kann mich von einem Absturz oder einem Zurück-Button-Exit oder einem benutzerdefinierten Menüelement Exit erholen oder zum Bildschirmbenutzer zurückkehren, der sich viele Tage später befand. - ToolmakerSteve 19. September 15 um 10:38


Jetzt bietet Android ViewModels zum Speichern des Status an. Sie sollten versuchen, dies anstelle von saveInstanceState zu verwenden.


Mit Icepick dieses Problem schnell lösenIcepick

Richten Sie zuerst die Bibliothek in ein app/build.gradle

repositories {
  maven {url "https://clojars.org/repo/"}
}
dependencies {
  compile 'frankiesardo:icepick:3.2.0'
  provided 'frankiesardo:icepick-processor:3.2.0'
}

Sehen wir uns nun dieses Beispiel an, um den Status in Activity zu speichern

public class ExampleActivity extends Activity {
  @State String username; // This will be automatically saved and restored

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Icepick.restoreInstanceState(this, savedInstanceState);
  }

  @Override public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    Icepick.saveInstanceState(this, outState);
  }
}

Es funktioniert für Aktivitäten, Fragmente oder jedes Objekt, das seinen Status für ein Bündel serialisieren muss (z. B. ViewPresenters für Mörtel).

Icepick kann auch den Instanzstatuscode für benutzerdefinierte Ansichten generieren:

class CustomView extends View {
  @State int selectedPosition; // This will be automatically saved and restored

  @Override public Parcelable onSaveInstanceState() {
    return Icepick.saveInstanceState(this, super.onSaveInstanceState());
  }

  @Override public void onRestoreInstanceState(Parcelable state) {
    super.onRestoreInstanceState(Icepick.restoreInstanceState(this, state));
  }

  // You can put the calls to Icepick into a BaseCustomView and inherit from it
  // All Views extending this CustomView automatically have state saved/restored
}

Nicht sicher, ob meine Lösung missbilligt wird oder nicht, aber ich verwende einen gebundenen Dienst, um den ViewModel-Status beizubehalten. Ob Sie es im Dienst im Speicher ablegen oder aus einer SqlLite-Datenbank abrufen und abrufen, hängt von Ihren Anforderungen ab. Dies ist, was Dienste jeder Art tun, sie bieten Dienste wie die Aufrechterhaltung des Anwendungsstatus und abstrakte allgemeine Geschäftslogik.

Aufgrund von Speicher- und Verarbeitungsbeschränkungen bei mobilen Geräten behandle ich Android-Ansichten ähnlich wie eine Webseite. Die Seite behält den Status nicht bei, es handelt sich lediglich um eine Präsentationsschichtkomponente, deren einziger Zweck darin besteht, den Anwendungsstatus darzustellen und Benutzereingaben zu akzeptieren. Jüngste Trends in der Web-App-Architektur verwenden das uralte MVC-Muster (Model, View, Controller), bei dem die Seite die View ist, die Domänendaten das Modell sind und der Controller hinter einem Webdienst sitzt. Das gleiche Muster kann in Android verwendet werden, wobei die Ansicht gut ist. Die Ansicht, das Modell sind Ihre Domänendaten und der Controller ist als Android-gebundener Dienst implementiert. Wann immer Sie möchten, dass eine Ansicht mit dem Controller interagiert, binden Sie beim Starten / Fortsetzen eine Verbindung dazu und bei Stopp / Pause die Bindung auf.

Dieser Ansatz bietet Ihnen den zusätzlichen Vorteil der Durchsetzung des Konstruktionsprinzips "Separation of Concern", da die gesamte Geschäftslogik Ihrer Anwendung in Ihren Service verschoben werden kann, wodurch doppelte Logik in mehreren Ansichten reduziert wird und die Ansicht die Erzwingung eines weiteren wichtigen Konstruktionsprinzips, "Single Responsibility", ermöglicht.


Um Boilerplate zu reduzieren, verwende ich Folgendes interfaceund classschreibe / schreibe in einen Bundlezum Speichern der Instanz.

Erstellen Sie zunächst eine Schnittstelle, die zum Annotieren Ihrer Instanzvariablen verwendet wird:

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({
        ElementType.FIELD
})
public @interface SaveInstance {

}

Erstellen Sie dann eine Klasse, in der Reflection zum Speichern von Werten im Bundle verwendet wird:

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;

import java.io.Serializable;
import java.lang.reflect.Field;

/**
 * Save and load fields to/from a {@link Bundle}. All fields should be annotated with {@link
 * SaveInstance}.</p>
 */
public class Icicle {

    private static final String TAG = "Icicle";

    /**
     * Find all fields with the {@link SaveInstance} annotation and add them to the {@link Bundle}.
     *
     * @param outState
     *         The bundle from {@link Activity#onSaveInstanceState(Bundle)} or {@link
     *         Fragment#onSaveInstanceState(Bundle)}
     * @param classInstance
     *         The object to access the fields which have the {@link SaveInstance} annotation.
     * @see #load(Bundle, Object)
     */
    public static void save(Bundle outState, Object classInstance) {
        save(outState, classInstance, classInstance.getClass());
    }

    /**
     * Find all fields with the {@link SaveInstance} annotation and add them to the {@link Bundle}.
     *
     * @param outState
     *         The bundle from {@link Activity#onSaveInstanceState(Bundle)} or {@link
     *         Fragment#onSaveInstanceState(Bundle)}
     * @param classInstance
     *         The object to access the fields which have the {@link SaveInstance} annotation.
     * @param baseClass
     *         Base class, used to get all superclasses of the instance.
     * @see #load(Bundle, Object, Class)
     */
    public static void save(Bundle outState, Object classInstance, Class<?> baseClass) {
        if (outState == null) {
            return;
        }
        Class<?> clazz = classInstance.getClass();
        while (baseClass.isAssignableFrom(clazz)) {
            String className = clazz.getName();
            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(SaveInstance.class)) {
                    field.setAccessible(true);
                    String key = className + "#" + field.getName();
                    try {
                        Object value = field.get(classInstance);
                        if (value instanceof Parcelable) {
                            outState.putParcelable(key, (Parcelable) value);
                        } else if (value instanceof Serializable) {
                            outState.putSerializable(key, (Serializable) value);
                        }
                    } catch (Throwable t) {
                        Log.d(TAG, "The field '" + key + "' was not added to the bundle");
                    }
                }
            }
            clazz = clazz.getSuperclass();
        }
    }

    /**
     * Load all saved fields that have the {@link SaveInstance} annotation.
     *
     * @param savedInstanceState
     *         The saved-instance {@link Bundle} from an {@link Activity} or {@link Fragment}.
     * @param classInstance
     *         The object to access the fields which have the {@link SaveInstance} annotation.
     * @see #save(Bundle, Object)
     */
    public static void load(Bundle savedInstanceState, Object classInstance) {
        load(savedInstanceState, classInstance, classInstance.getClass());
    }

    /**
     * Load all saved fields that have the {@link SaveInstance} annotation.
     *
     * @param savedInstanceState
     *         The saved-instance {@link Bundle} from an {@link Activity} or {@link Fragment}.
     * @param classInstance
     *         The object to access the fields which have the {@link SaveInstance} annotation.
     * @param baseClass
     *         Base class, used to get all superclasses of the instance.
     * @see #save(Bundle, Object, Class)
     */
    public static void load(Bundle savedInstanceState, Object classInstance, Class<?> baseClass) {
        if (savedInstanceState == null) {
            return;
        }
        Class<?> clazz = classInstance.getClass();
        while (baseClass.isAssignableFrom(clazz)) {
            String className = clazz.getName();
            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(SaveInstance.class)) {
                    String key = className + "#" + field.getName();
                    field.setAccessible(true);
                    try {
                        Object fieldVal = savedInstanceState.get(key);
                        if (fieldVal != null) {
                            field.set(classInstance, fieldVal);
                        }
                    } catch (Throwable t) {
                        Log.d(TAG, "The field '" + key + "' was not retrieved from the bundle");
                    }
                }
            }
            clazz = clazz.getSuperclass();
        }
    }

}

Verwendungsbeispiel:

public class MainActivity extends Activity {

    @SaveInstance
    private String foo;

    @SaveInstance
    private int bar;

    @SaveInstance
    private Intent baz;

    @SaveInstance
    private boolean qux;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Icicle.load(savedInstanceState, this);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        Icicle.save(outState, this);
    }

}

Hinweis: Dieser Code wurde aus einem Bibliotheksprojekt namens AndroidAutowire das unter der MIT-Lizenz lizenziert ist .


Um Daten zum Aktivitätsstatus onCreate()abzurufen, müssen Sie die Daten zuerst in saveInstanceState speichern, indem Sie die SaveInstanceState(Bundle savedInstanceState)Methode überschreiben .

Wenn die Aktivität destroy- SaveInstanceState(Bundle savedInstanceState)Methode aufgerufen wird und dort die Daten speichert, die Sie speichern möchten. Sie erhalten dasselbe, onCreate()wenn die Aktivität neu gestartet wird.





application-state