In diesem Leitfaden werden die Erwartungen der Nutzer bezüglich des UI-Status und die verfügbaren Optionen erläutert. zur Beibehaltung des Zustands.
Das Speichern und Wiederherstellen des UI-Status einer Aktivität nach einer Aktivitäten oder Anwendungen werden essenziell für einen guten Benutzer Nutzererfahrung. Nutzer erwarten, dass der Status der Benutzeroberfläche gleich bleibt, aber das System kann und zerstören Sie die Aktivität und ihren gespeicherten Status.
Um die Lücke zwischen Nutzererwartung und Systemverhalten zu schließen, Kombination der folgenden Methoden:
ViewModel
-Objekte.- Gespeicherte Instanzstatus in den folgenden Kontexten:
<ph type="x-smartling-placeholder">
- </ph>
- Jetpack Compose:
rememberSaveable
. - Ansichten:
onSaveInstanceState()
API. - ViewModels:
SavedStateHandle
- Jetpack Compose:
- Lokaler Speicher zum Beibehalten des UI-Status bei App- und Aktivitätsübergängen
Die optimale Lösung hängt von der Komplexität Ihrer UI-Daten, der Verwendung und ein Gleichgewicht zwischen Geschwindigkeit des Datenzugriffs und Speichernutzung finden.
Sicherstellen, dass die App den Anforderungen der Nutzer entspricht Erwartungen und bietet eine schnelle, . Vermeiden Sie Verzögerungen beim Laden von Daten in die Benutzeroberfläche, insbesondere nach häufigen Konfigurationsänderungen wie die Rotation.
Nutzererwartungen und Systemverhalten
Abhängig von der Aktion, die Nutzende durchführen, erwarten sie entweder, dass der Aktivitätsstatus gelöscht oder der Zustand beibehalten werden soll. In einigen Fällen kann das System was die Nutzenden erwarten. In anderen Fällen benötigt das System was die Nutzenden erwarten.
Vom Nutzer initiierte Ablehnung des UI-Status
Der Nutzer erwartet, dass beim Starten einer Aktivität der vorübergehende UI-Status Diese Aktivität bleibt gleich, bis der Nutzer sie vollständig schließt. So kann der Nutzer eine Aktivität vollständig schließen:
- Wischen Sie die Aktivität aus dem Bildschirm „Übersicht (Letzte)“.
- Beenden der App über den Bildschirm „Einstellungen“ oder erzwungenes Beenden der App
- Das Gerät wird neu gestartet.
- Eine Art „Fertigstellen“ Aktion (die durch
Activity.finish()
.
Die Nutzenden gehen in diesen vollständigen Ablehnungsfällen davon aus, dass sie die Aktivität dauerhaft verlassen haben, erwarten sie, dass die Aktivität in einem sauberen Zustand beginnt. Das zugrunde liegende System dass das Verhalten der Nutzer den Erwartungen entspricht: wird die Activity-Instanz gelöscht und zusammen mit und jeden gespeicherten Instanzstatuseintrag, der mit dem Aktivitäten.
Es gibt einige Ausnahmen von dieser Regel bezüglich vollständiger Ablehnungen, z. B. eine erwarten Nutzer, dass sie von einem Browser genau auf die Webseite gelangen, die sie gesucht haben. bevor sie den Browser über die Schaltfläche „Zurück“ verlassen haben.
Vom System initiierte Ablehnung des UI-Status
Ein Nutzer erwartet, dass der UI-Status einer Aktivität während einer Konfigurationsänderung, z. B. Drehung oder Wechsel in den Mehrfenstermodus. Standardmäßig zerstört das System die Aktivität, wenn eine solche Konfiguration Änderung auftritt, wodurch alle in der Activity-Instanz gespeicherten UI-Status gelöscht werden. Bis Weitere Informationen zu Gerätekonfigurationen finden Sie in der Konfigurationsreferenzseite. Hinweis: Dies ist möglich, wird aber nicht empfohlen. um das Standardverhalten für Konfigurationsänderungen zu überschreiben. Weitere Informationen finden Sie unter Handhabung der selbst konfigurieren.
Nutzer erwarten außerdem, dass der UI-Status Ihrer Aktivität gleich bleibt, wenn sie wechseln Sie vorübergehend zu einer anderen App und kehren Sie später zu Ihrer App zurück. Für Beispiel: Der Nutzer führt eine Suche in Ihrer Suchaktivität durch und drückt dann die Startbildschirmtaste oder einen Anruf entgegennimmt, wenn er zur Suchaktivität zurückkehrt erwarten sie, dass das Keyword und die Ergebnisse für die Suche weiterhin vorhanden sind, genau wie vorher.
In diesem Szenario wird die App im Hintergrund platziert und das System kann sein Bestes. damit der App-Prozess im Arbeitsspeicher Es kann jedoch sein, dass das System während der Nutzer nicht mit anderen Apps interagiert. In solchen Fällen in einem Fall wird die Activity-Instanz mit allen darin gespeicherten Statusdaten gelöscht. Wenn der Nutzer die App neu startet, ist die Aktivität unerwartet bereinigt. Weitere Informationen zum Beenden von Prozessen finden Sie unter Prozesse und Anwendungslebenszyklus.
Optionen zum Beibehalten des UI-Status
Wenn die Erwartungen der Nutzenden an den Status der Benutzeroberfläche nicht mit dem Standardsystem übereinstimmen muss der Status der Benutzeroberfläche des Nutzers gespeichert und wiederhergestellt werden. vom System initiierte Löschung ist für den Nutzer transparent.
Die Optionen zum Beibehalten des UI-Status variieren je nach den folgenden Dimensionen: die sich auf die User Experience auswirken:
ViewModel | Status der gespeicherten Instanz | Nichtflüchtiger Speicher | |
---|---|---|---|
Speicherort | im Arbeitsspeicher | im Arbeitsspeicher | auf Datenträger oder im Netzwerk |
Überlebt Konfigurationsänderung | Ja | Ja | Ja |
Überlebt den Tod eines vom System initiierten Prozesses | Nein | Ja | Ja |
Überlebt das Schließen der Nutzeraktivität/onFinish() | Nein | Nein | Ja |
Dateneinschränkungen | komplexe Objekte sind in Ordnung, aber der Platz ist durch den verfügbaren Arbeitsspeicher begrenzt. | Nur für primitive Typen und einfache, kleine Objekte wie String | nur begrenzt durch Speicherplatz oder Kosten / Zeit des Abrufs von der Netzwerkressource |
Lese-/Schreibzeit | schnell (nur Arbeitsspeicherzugriff) | langsam (erfordert Serialisierung/Deserialisierung) | langsam (erfordert Festplattenzugriff oder Netzwerktransaktion) |
Konfigurationsänderungen mit ViewModel verarbeiten
ViewModel eignet sich ideal zum Speichern und Verwalten von UI-Daten, während der Nutzer die Anwendung aktiv nutzen. Sie ermöglicht schnellen Zugriff auf Daten der Benutzeroberfläche und hilft Ihnen, den erneuten Abruf von Daten aus dem Netzwerk oder der Festplatte durch Rotation, Fenstergröße und andere häufig auftretende Konfigurationsänderungen. Um zu erfahren, wie Sie ein ViewModel finden Sie im ViewModel-Leitfaden.
ViewModel behält die Daten im Speicher bei, sodass es kostengünstiger ist, sie abzurufen als Daten von der Festplatte oder dem Netzwerk abzurufen. Ein ViewModel ist mit einer Aktivität verknüpft (oder ein anderer Lebenszyklusinhaber) – er bleibt während einer Konfiguration im Arbeitsspeicher geändert wird und das ViewModel automatisch mit dem neuen Aktivitätsinstanz, die sich aus der Konfigurationsänderung ergibt.
ViewModels werden automatisch vom System gelöscht, wenn der Nutzer
Ihrer Aktivität bzw. Ihrem Fragment oder wenn Sie finish()
aufrufen, was bedeutet, dass der Status
wie vom Nutzer erwartet gelöscht.
Im Gegensatz zum gespeicherten Instanzstatus werden ViewModels während einer vom System initiierten
Prozessbeendigung. Um Daten neu zu laden, nachdem ein vom System initiierter Prozess in einem
ViewModel verwenden Sie die SavedStateHandle
API. Wenn die Daten dagegen
die mit der Benutzeroberfläche zusammenhängen und nicht im ViewModel enthalten sein müssen, verwenden Sie
onSaveInstanceState()
im Ansichtssystem oder rememberSaveable
in Jetpack
Schreiben. Wenn es sich bei den Daten um Anwendungsdaten handelt, ist es möglicherweise besser,
es auf der Festplatte gespeichert.
Wenn Sie bereits eine In-Memory-Lösung zum Speichern des UI-Status haben müssen Sie ViewModel möglicherweise nicht verwenden.
Gespeicherten Instanzstatus als Sicherung verwenden, um den vom System initiierten Prozess zu beenden
Den onSaveInstanceState()
-Callback im Ansichtssystem
rememberSaveable
in Jetpack Compose und SavedStateHandle
in Jetpack Compose
ViewModels speichert Daten, die zum erneuten Laden des Status eines UI-Controllers erforderlich sind, z. B.
Aktivität oder ein Fragment, wenn das System dies zerstört und später
Controller. So implementieren Sie den gespeicherten Instanzstatus mithilfe von
onSaveInstanceState
, siehe Aktivitätsstatus speichern und wiederherstellen in der
Leitfaden zum Aktivitätslebenszyklus
Gespeicherte Instanzstatus-Bundles bleiben sowohl bei Konfigurationsänderungen als auch sind jedoch durch Speicher und Geschwindigkeit begrenzt, da die verschiedenen APIs Daten serialisieren. Die Serialisierung kann viel Arbeitsspeicher verbrauchen, wenn die Objekte, serialisiert werden, kompliziert. Weil dieser Vorgang im Hauptthread erfolgt während einer Konfigurationsänderung führt, kann eine Serialisierung mit langer Ausführungszeit dazu führen, und das visuelle Rauschen.
Verwenden Sie den gespeicherten Instanzstatus nicht zum Speichern großer Datenmengen, z. B. Bitmaps,
noch komplexe Datenstrukturen,
die eine lange Serialisierung erfordern,
Deserialisierung. Speichern Sie stattdessen nur primitive Typen und einfache, kleine Objekte.
wie String
. Verwenden Sie daher den gespeicherten Instanzstatus, um eine minimale Menge an
Daten, die erforderlich sind, z. B. eine ID, um die Daten neu zu erstellen, die zur Wiederherstellung der Benutzeroberfläche erforderlich sind
für den Fall, dass die anderen Persistenzmechanismen fehlschlagen, Meiste
Apps sollten dies implementieren, um den vom System initiierten Prozess zu beheben.
Je nach Anwendungsfall Ihrer Anwendung müssen Sie gespeicherte Instanzen möglicherweise nicht verwenden überhaupt nicht. Beispielsweise kann ein Browser die Nutzenden zurück zu der Webseite, die sie vor dem Verlassen des Browsers aufgerufen haben. Wenn Ihre Aktivitäten sich so verhält, können Sie auf den gespeicherten Instanzstatus verzichten und stattdessen alles lokal abrufen.
Wenn Sie eine Aktivität von einem Intent aus öffnen, wird das Bündel von Extras an die Aktivität geliefert wird, wenn sich die Konfiguration ändert, die Aktivität wiederherstellt. Wenn ein UI-Statusdatenelement, z. B. eine Suche, als zusätzliche Intent übergeben wurden, als die Aktivität gestartet wurde, kann das Extras-Bundle anstelle des gespeicherten Instanzstatus-Bundles verwenden. Weitere Informationen Weitere Informationen zu Intent-Extras finden Sie unter Intent- und Intent-Filter.
In beiden Fällen sollten Sie ein ViewModel
verwenden, um
zum erneuten Laden von Daten
aus der Datenbank während einer Konfigurationsänderung.
In Fällen, in denen die UI-Daten einfach und kompakt sind, können Sie mit gespeicherten Instanzstatus-APIs die Statusdaten erhalten.
Mit SavedStateRegistry in den gespeicherten Status einhängen
Ab Fragment 1.1.0 oder dessen transitive Abhängigkeit Activity
1.0.0, UI-Controller wie Activity
oder Fragment
, implementieren
SavedStateRegistryOwner
und geben Sie SavedStateRegistry
an,
die an diesen Verantwortlichen gebunden sind. Mit SavedStateRegistry
können Komponenten verbunden werden in
des UI-Controllers gespeichert,
um ihn zu nutzen oder beizutragen. Beispiel:
Das Modul „Saved State“ für ViewModel erstellt mit SavedStateRegistry
eine
SavedStateHandle
und stellen Sie sie Ihren ViewModel
-Objekten bereit. Sie können die Daten abrufen,
den SavedStateRegistry
in Ihrem UI-Controller durch Aufrufen von
getSavedStateRegistry()
Komponenten, die zum gespeicherten Status beitragen, müssen
SavedStateRegistry.SavedStateProvider
, mit dem eine einzelne Methode definiert wird
mit dem Namen saveState()
. Mit der Methode saveState()
kann Ihre Komponente
gibt ein Bundle
zurück, das alle Statuswerte enthält, die von dieser Komponente gespeichert werden sollen.
SavedStateRegistry
ruft diese Methode während der Speicherphase der Benutzeroberfläche auf
des Lebenszyklus des Controllers.
Kotlin
class SearchManager : SavedStateRegistry.SavedStateProvider { companion object { private const val QUERY = "query" } private val query: String? = null ... override fun saveState(): Bundle { return bundleOf(QUERY to query) } }
Java
class SearchManager implements SavedStateRegistry.SavedStateProvider { private static String QUERY = "query"; private String query = null; ... @NonNull @Override public Bundle saveState() { Bundle bundle = new Bundle(); bundle.putString(QUERY, query); return bundle; } }
Um eine SavedStateProvider
zu registrieren, rufen Sie registerSavedStateProvider()
auf unter
SavedStateRegistry
und übergeben einen Schlüssel, der mit den Daten des Anbieters verknüpft werden soll als
und dem Anbieter. Die zuvor für den Anbieter gespeicherten Daten können
durch Aufrufen von consumeRestoredStateForKey()
aus dem gespeicherten Status abgerufen
in der SavedStateRegistry
, wobei der Schlüssel übergeben wird, der mit der Methode
Daten.
Innerhalb von Activity
oder Fragment
können Sie SavedStateProvider
in
onCreate()
nach dem Anruf bei super.onCreate()
. Alternativ können Sie
LifecycleObserver
auf einem SavedStateRegistryOwner
, bei dem Folgendes implementiert wird:
LifecycleOwner
und registrieren Sie die SavedStateProvider
, sobald die
Es findet ON_CREATE
statt. Mit einem LifecycleObserver
können Sie das
die Registrierung und der Abruf des zuvor gespeicherten Status aus dem
SavedStateRegistryOwner
selbst.
Kotlin
class SearchManager(registryOwner: SavedStateRegistryOwner) : SavedStateRegistry.SavedStateProvider { companion object { private const val PROVIDER = "search_manager" private const val QUERY = "query" } private val query: String? = null init { // Register a LifecycleObserver for when the Lifecycle hits ON_CREATE registryOwner.lifecycle.addObserver(LifecycleEventObserver { _, event -> if (event == Lifecycle.Event.ON_CREATE) { val registry = registryOwner.savedStateRegistry // Register this object for future calls to saveState() registry.registerSavedStateProvider(PROVIDER, this) // Get the previously saved state and restore it val state = registry.consumeRestoredStateForKey(PROVIDER) // Apply the previously saved state query = state?.getString(QUERY) } } } override fun saveState(): Bundle { return bundleOf(QUERY to query) } ... } class SearchFragment : Fragment() { private var searchManager = SearchManager(this) ... }
Java
class SearchManager implements SavedStateRegistry.SavedStateProvider { private static String PROVIDER = "search_manager"; private static String QUERY = "query"; private String query = null; public SearchManager(SavedStateRegistryOwner registryOwner) { registryOwner.getLifecycle().addObserver((LifecycleEventObserver) (source, event) -> { if (event == Lifecycle.Event.ON_CREATE) { SavedStateRegistry registry = registryOwner.getSavedStateRegistry(); // Register this object for future calls to saveState() registry.registerSavedStateProvider(PROVIDER, this); // Get the previously saved state and restore it Bundle state = registry.consumeRestoredStateForKey(PROVIDER); // Apply the previously saved state if (state != null) { query = state.getString(QUERY); } } }); } @NonNull @Override public Bundle saveState() { Bundle bundle = new Bundle(); bundle.putString(QUERY, query); return bundle; } ... } class SearchFragment extends Fragment { private SearchManager searchManager = new SearchManager(this); ... }
Lokale Persistenz verwenden, um den Prozessabschluss bei komplexen oder großen Daten zu bewältigen
Nichtflüchtiger lokaler Speicher, z. B. eine Datenbank oder gemeinsame Einstellungen, bleibt erhalten. solange Ihre Anwendung auf dem Gerät des Nutzers installiert ist (es sei denn, Nutzer die Daten für Ihre App löscht). Ein solcher lokaler Speicher bleibt die vom System initiierte Aktivität und der Anwendungsprozess beendet werden, kann es teuer sein, abgerufen, da er aus dem lokalen Speicher im Arbeitsspeicher gelesen werden muss. Häufig Dieser nichtflüchtige lokale Speicher ist möglicherweise bereits Teil Ihrer Anwendung Architektur alle Daten speichern, die nicht verloren gehen sollen, wenn Sie die Aktivitäten.
Weder ViewModel noch der gespeicherte Instanzstatus sind langfristige Speicherlösungen. sind daher kein Ersatz für einen lokalen Speicher wie eine Datenbank. Stattdessen sollten diese Mechanismen nur zur temporären Speicherung des UI-Status vorübergehend verwenden und Nichtflüchtigen Speicher für andere App-Daten verwenden Siehe Leitfaden zur Anwendungsarchitektur für weitere Informationen dazu, wie du lokalen Speicher nutzen kannst, um dein App-Modell beizubehalten (z.B. bei einem Neustart des Geräts).
UI-Status verwalten: Teilung und Eroberung
Sie können den Status der Benutzeroberfläche effizient speichern und wiederherstellen, indem Sie die Arbeit zwischen den verschiedene Arten von Persistenzmechanismen. In den meisten Fällen wird jeder dieser Mechanismen Daten, die in der Aktivität verwendet werden, basierend auf dem Kompromisse bei Datenkomplexität, Zugriffsgeschwindigkeit und Lebensdauer:
- Lokale Persistenz: Speichert alle Anwendungsdaten, die bei folgenden Ereignissen nicht verloren gehen sollen.
die Aktivität öffnen und schließen.
- Beispiel: Eine Sammlung von Songobjekten, die Audiodateien enthalten können und Metadaten.
ViewModel
: Speichert alle Daten im Arbeitsspeicher, die zum Anzeigen des der zugehörigen UI, den Status der Bildschirm-UI.- Beispiel: Die Titelobjekte bei der letzten Suche und der letzten Suche Suchanfrage.
- Gespeicherter Instanzstatus: Speichert eine kleine Datenmenge, die für das Neuladen erforderlich ist
UI-Status, wenn das System anhält und dann die Benutzeroberfläche neu erstellt Anstelle von
um komplexe Objekte zu speichern, werden die
komplexen Objekte im lokalen Speicher
Eine eindeutige ID für diese Objekte in den gespeicherten Instanzstatus-APIs.
- Beispiel: Die letzte Suchanfrage wird gespeichert.
Stellen Sie sich als Beispiel eine Aktivität vor, bei der Sie der Songs aus unserer Mediathek. So sollten verschiedene Ereignisse gehandhabt werden:
Wenn der Nutzer einen Song hinzufügt, delegiert ViewModel
sofort das
diese Daten lokal bereitstellen. Soll der neu hinzugefügte Song auf der Benutzeroberfläche angezeigt werden,
sollten auch die Daten im ViewModel
-Objekt aktualisieren, um die Hinzufügung von
des Songs. Denken Sie daran, alle Datenbankeinfügungen aus dem Hauptthread heraus vorzunehmen.
Wenn der Nutzer nach einem Song sucht, sind die komplexen Titeldaten, die Sie aus dem
sollte sie sofort im ViewModel
-Objekt als Teil der
Bildschirm-UI-Status angezeigt.
Wenn die Aktivität in den Hintergrund verschoben wird und das System die gespeicherten
Instanzstatus-APIs muss die Suchanfrage im Status der gespeicherten Instanz gespeichert werden,
falls der Prozess neu erstellt wird. Da die Informationen zum Laden der
App-Daten beibehalten, Suchanfrage im ViewModel speichern
SavedStateHandle
Das sind alle Informationen, die Sie
zum Laden der Daten und
die Benutzeroberfläche in ihren aktuellen Zustand zurückversetzen.
Komplexe Zustände wiederherstellen: Teile zusammensetzen
Wenn es Zeit ist, dass Nutzende zur Aktivität zurückkehren, gibt es zwei mögliche Szenarien für die Neuerstellung der Aktivität:
- Die Aktivität wird neu erstellt, nachdem sie vom System angehalten wurde. Die
die Abfrage in einem gespeicherten Instanzstatus-Bundle gespeichert ist, und die UI
sollte die Abfrage an
ViewModel
übergeben, wennSavedStateHandle
nicht verwendet wird.ViewModel
erkennt, dass keine Suchergebnisse im Cache gespeichert wurden, und delegiert Laden der Suchergebnisse anhand der gegebenen Suchanfrage. - Die Aktivität wird nach einer Konfigurationsänderung erstellt. Seit dem
ViewModel
Instanz nicht gelöscht wurde, sind imViewModel
alle Informationen im Cache gespeichert. und muss die Datenbank nicht noch einmal abfragen.
Weitere Informationen
Weitere Informationen zum Speichern von UI-Statuswerten finden Sie in den folgenden Ressourcen.
Blogs
- ViewModels: Ein einfaches Beispiel
- ViewModels: Persistence,
onSaveInstanceState()
, Wiederherstellung des UI-Status und Ladeprogramme - Codelab zu Android-Komponenten für den Lebenszyklus
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Modul „Saved State“ für ViewModel
- Lebenszyklen mit lebenszyklusbezogenen Komponenten verarbeiten
- ViewModel – Übersicht