Wenn ein Nutzer Ihre App aufruft, verlässt und wieder aufruft, durchlaufen die Activity-Instanzen in Ihrer App verschiedene Status in ihrem Lebenszyklus.
Die Klasse Activity bietet eine Reihe von Callbacks, die die Aktivität darüber informieren, wenn sich ein Status ändert oder das System eine Aktivität erstellt, beendet oder fortsetzt oder den Prozess zerstört, in dem sich die Aktivität befindet.
In den Lebenszyklus-Callback-Methoden können Sie festlegen, wie sich Ihre Aktivität verhält, wenn der Nutzer die Aktivität verlässt und wieder aufruft. Wenn Sie beispielsweise einen Videoplayer für Streaming entwickeln, können Sie das Video pausieren und die Netzwerkverbindung beenden, wenn der Nutzer zu einer anderen App wechselt. Wenn der Nutzer zurückkehrt, können Sie die Verbindung zum Netzwerk wiederherstellen und das Video an derselben Stelle fortsetzen.
Mit jedem Callback können Sie bestimmte Aufgaben ausführen, die für eine bestimmte Statusänderung geeignet sind. Wenn Sie die richtigen Aufgaben zur richtigen Zeit erledigen und Übergänge richtig handhaben, wird Ihre App robuster und leistungsfähiger. Eine gute Implementierung der Lebenszyklus-Callbacks kann beispielsweise dazu beitragen, Folgendes zu vermeiden:
- Abstürze, wenn der Nutzer einen Anruf erhält oder zu einer anderen App wechselt, während er deine App verwendet.
- Verbraucht wertvolle Systemressourcen, wenn der Nutzer sie nicht aktiv verwendet.
- Der Fortschritt des Nutzers geht verloren, wenn er die App verlässt und später zurückkehrt.
- Abstürze oder Verlust des Nutzerfortschritts, wenn der Bildschirm zwischen Quer- und Hochformat gedreht wird.
In diesem Dokument wird der Aktivitätslebenszyklus im Detail erläutert. Das Dokument beginnt mit einer Beschreibung des Lebenszyklusparadigmas. Anschließend werden die einzelnen Callbacks erläutert: was intern während der Ausführung passiert und was Sie währenddessen implementieren müssen.
Anschließend wird kurz die Beziehung zwischen dem Aktivitätsstatus und der Anfälligkeit eines Prozesses für das Beenden durch das System erläutert. Schließlich werden mehrere Themen im Zusammenhang mit Übergängen zwischen Aktivitätszuständen erläutert.
Informationen zum Umgang mit Lebenszyklen, einschließlich Best Practices, finden Sie unter Lebenszyklus in Jetpack Compose und UI-Zustände speichern. Informationen zum Erstellen einer robusten App in Produktionsqualität mit Aktivitäten in Kombination mit Architekturkomponenten finden Sie im Leitfaden zur App-Architektur.
Konzepte des Aktivitätslebenszyklus
Für die Übergänge zwischen den Phasen des Aktivitätslebenszyklus bietet die Klasse Activity sechs wichtige Callbacks: onCreate, onStart, onResume, onPause, onStop und onDestroy. Das System ruft jeden dieser Callbacks auf, wenn die Aktivität in einen neuen Status wechselt.
Abbildung 1 zeigt eine visuelle Darstellung dieses Paradigmas.
Wenn der Nutzer die Aktivität verlässt, ruft das System Methoden auf, um die Aktivität zu beenden. In einigen Fällen wird die Aktivität nur teilweise abgebaut und verbleibt im Arbeitsspeicher, z. B. wenn der Nutzer zu einer anderen App wechselt. In diesen Fällen kann die Aktivität wieder in den Vordergrund rücken.
Wenn der Nutzer zur Aktivität zurückkehrt, wird sie an der Stelle fortgesetzt, an der er sie verlassen hat. Mit wenigen Ausnahmen ist es Apps nicht gestattet, Aktivitäten zu starten, wenn sie im Hintergrund ausgeführt werden.
Die Wahrscheinlichkeit, dass das System einen bestimmten Prozess und die darin enthaltenen Aktivitäten beendet, hängt vom Status der Aktivität zu diesem Zeitpunkt ab. Weitere Informationen zur Beziehung zwischen Status und Anfälligkeit für das Beenden finden Sie im Abschnitt Aktivitätsstatus und Beenden aus dem Arbeitsspeicher.
Je nach Komplexität Ihrer Aktivität müssen Sie wahrscheinlich nicht alle Lebenszyklusmethoden implementieren. Es ist jedoch wichtig, dass Sie die einzelnen Optionen verstehen und diejenigen implementieren, die dafür sorgen, dass sich Ihre App so verhält, wie es die Nutzer erwarten.
Compose und der Lebenszyklus
Vermeiden Sie es in Compose, Geschäftslogik oder manuelle Beobachter direkt in Aktivitäts-Callbacks wie onStart oder onResume zu platzieren. Verwende stattdessen lebenszyklusbewusste Effekte und zustandsbewusste Beobachter, die sich automatisch an die Darstellung der Benutzeroberfläche auf dem Bildschirm anpassen.
- Lebenszyklusbewusste Erfassung: Verwenden Sie
collectAsStateWithLifecycle, um Abläufe aus IhremViewModelzu nutzen. Diese API beginnt automatisch mit der Erfassung, wenn die UI in den Status „Gestartet“ wechselt, und stoppt, wenn sie in den Hintergrund wechselt. So wird unnötiger Ressourcenverbrauch vermieden. Nachdem Sie den Ablauf als Status erfasst haben, können Sie mitLifecycleEffectsCode ausführen, wenn ein Lifecycle-Event auftritt. - Logikfluss: Durch die Verwendung dieser APIs reagiert die Benutzeroberfläche über den Kompositionsbaum auf natürliche Weise auf den Lebenszyklusstatus. So wird sichergestellt, dass die Geschäftslogik nur ausgeführt wird, wenn der Nutzer aktiv mit der Komponente interagiert.
Weitere Informationen zu Compose und dem Lebenszyklus finden Sie unter Lebenszyklus in Jetpack Compose.
Lebenszyklus-Callbacks
Dieser Abschnitt enthält Informationen zum Konzept und zur Implementierung der Callback-Methoden, die während des Aktivitätslebenszyklus verwendet werden.
Einige Aktionen gehören in die Methoden des Aktivitätslebenszyklus. Platzieren Sie jedoch Code, der die Aktionen einer abhängigen Komponente implementiert, in der Komponente und nicht in der Methode des Aktivitätslebenszyklus. Dazu müssen Sie die abhängige Komponente lebenszyklusbewusst machen. Informationen dazu, wie Sie Ihre abhängigen Komponenten lebenszyklusbewusst machen, finden Sie unter Lebenszyklus in Jetpack Compose.
onCreate
Du musst diesen Callback implementieren, der ausgelöst wird, wenn das System die Aktivität zum ersten Mal erstellt. Bei der Erstellung der Aktivität wechselt sie in den Status Erstellt. In der Methode onCreate wird die grundlegende Startlogik der Anwendung ausgeführt, die nur einmal während der gesamten Lebensdauer der Aktivität erfolgt.
Beispielsweise könnte Ihre Implementierung von onCreate Daten an Listen binden, die Aktivität mit einem ViewModel verknüpfen und einige Variablen auf Klassenebene instanziieren. Diese Methode empfängt den Parameter savedInstanceState, ein Bundle-Objekt, das den zuvor gespeicherten Status der Aktivität enthält. Wenn die Aktivität noch nie existiert hat, ist der Wert des Bundle-Objekts null.
Wenn Sie eine lebenszyklusbewusste Komponente haben, die mit dem Lebenszyklus Ihrer Aktivität verknüpft ist, empfängt sie das Ereignis ON_CREATE. Die mit @OnLifecycleEvent annotierte Methode wird aufgerufen, damit die lebenszyklusbewusste Komponente den erforderlichen Einrichtungscode für den erstellten Status ausführen kann.
Das folgende Beispiel zeigt, wie Sie eine Text komponierbare Funktion in eine minimale Activity einbinden:
class ExampleActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { // In here, we can call composables! MaterialTheme { Greeting(name = "compose") } } } } @Composable fun Greeting(name: String) { Text(text = "Hello $name!") }
Ihre Aktivität bleibt nicht im Status „Erstellt“. Nachdem die Methode onCreate ausgeführt wurde, wechselt die Aktivität in den Status Gestartet und das System ruft die Methoden onStart und onResume in schneller Folge auf.
onStart
Wenn die Aktivität den Status „Gestartet“ erreicht, ruft das System onStart auf.
Durch diesen Aufruf wird die Aktivität für den Nutzer sichtbar, während die App die Aktivität darauf vorbereitet, in den Vordergrund zu treten und interaktiv zu werden. In dieser Methode wird beispielsweise der Code initialisiert, der die Benutzeroberfläche verwaltet.
Wenn die Aktivität in den Status „Gestartet“ wechselt, empfängt jede lebenszyklusbewusste Komponente, die an den Lebenszyklus der Aktivität gebunden ist, das Ereignis ON_START.
Die Methode onStart wird schnell abgeschlossen und die Aktivität bleibt wie beim Status „Erstellt“ nicht im Status „Gestartet“. Sobald dieser Callback abgeschlossen ist, wechselt die Aktivität in den Status Fortgesetzt und das System ruft die Methode onResume auf.
onResume
Wenn die Aktivität in den Status „Fortgesetzt“ wechselt, wird sie in den Vordergrund gestellt und das System ruft den Callback onResume auf. In diesem Zustand interagiert die App mit dem Nutzer. Die App bleibt in diesem Zustand, bis etwas passiert, das den Fokus von der App wegnimmt, z. B. ein eingehender Anruf, der Wechsel zu einer anderen Aktivität oder das Ausschalten des Displays.
Wenn die Aktivität in den Status „Fortgesetzt“ wechselt, empfängt jede lebenszyklusabhängige Komponente, die an den Lebenszyklus der Aktivität gebunden ist, das Ereignis ON_RESUME. Hier können die Lebenszykluskomponenten alle Funktionen aktivieren, die ausgeführt werden müssen, während die Komponente sichtbar und im Vordergrund ist, z. B. das Starten einer Kameravorschau.
Wenn ein unterbrechendes Ereignis auftritt, wechselt die Aktivität in den Status Pausiert und das System ruft den Callback onPause auf.
Wenn die Aktivität vom Status „Pausiert“ in den Status „Fortgesetzt“ zurückkehrt, ruft das System die Methode onResume noch einmal auf. Implementiere daher onResume, um Komponenten zu initialisieren, die du während onPause freigibst, und um alle anderen Initialisierungen durchzuführen, die jedes Mal erfolgen müssen, wenn die Aktivität in den Status „Fortgesetzt“ wechselt.
Hier ist ein Beispiel für eine lebenszyklusbewusste Komponente, die auf die Kamera zugreift, wenn die Komponente das Ereignis ON_RESUME empfängt:
class CameraComponent : LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun initializeCamera() {
if (camera == null) {
getCamera()
}
}
...
}
Der vorherige Code initialisiert die Kamera, sobald die LifecycleObserver das Ereignis ON_RESUME empfängt. Im Mehrfenstermodus ist die Aktivität jedoch möglicherweise vollständig sichtbar, auch wenn sie sich im Status „Pausiert“ befindet. Wenn sich die App beispielsweise im Mehrfenstermodus befindet und der Nutzer auf das Fenster tippt, das deine Aktivität nicht enthält, wechselt deine Aktivität in den Status „Pausiert“.
Wenn die Kamera nur aktiv sein soll, wenn die App fortgesetzt wird (sichtbar und aktiv im Vordergrund), initialisieren Sie die Kamera nach dem zuvor gezeigten ON_RESUME-Ereignis. Wenn die Kamera aktiv bleiben soll, während die Aktivität pausiert, aber sichtbar ist, z. B. im Mehrfenstermodus, initialisiere die Kamera nach dem ON_START-Ereignis.
Wenn die Kamera jedoch aktiv ist, während deine Aktivität pausiert ist, kann der Zugriff auf die Kamera für eine andere fortgesetzte App im Mehrfenstermodus verweigert werden. Manchmal ist es notwendig, die Kamera aktiv zu halten, während die Aktivität pausiert ist. Dies kann jedoch die allgemeine Nutzererfahrung beeinträchtigen.
Überlege dir daher genau, an welcher Stelle im Lebenszyklus es am sinnvollsten ist, im Kontext des Mehrfenstermodus die Kontrolle über freigegebene Systemressourcen zu übernehmen. Weitere Informationen zur Unterstützung des Mehrfenstermodus finden Sie unter Mehrfenstermodus unterstützen.
Unabhängig davon, in welchem Build-up-Ereignis Sie einen Initialisierungsvorgang ausführen, müssen Sie das entsprechende Lifecycle-Event verwenden, um die Ressource freizugeben. Wenn Sie etwas nach dem ON_START-Ereignis initialisieren, geben Sie es nach dem ON_STOP-Ereignis frei oder beenden Sie es. Wenn Sie nach dem Ereignis ON_RESUME initialisieren, geben Sie nach dem Ereignis ON_PAUSE frei.
Im obigen Code-Snippet wird der Code für die Kamerainitialisierung in einer lebenszyklusbewussten Komponente platziert. Sie können diesen Code stattdessen direkt in die Lebenszyklus-Callbacks der Aktivität einfügen, z. B. onStart und onStop. Wir raten jedoch davon ab. Wenn Sie diese Logik einer unabhängigen, lebenszyklusbewussten Komponente hinzufügen, können Sie die Komponente für mehrere Aktivitäten wiederverwenden, ohne Code duplizieren zu müssen. Informationen zum Erstellen einer lebenszyklusbewussten Komponente finden Sie unter Lebenszyklus in Jetpack Compose.
onPause
Das System ruft diese Methode als ersten Hinweis darauf auf, dass der Nutzer die Aktivität verlässt. Das bedeutet jedoch nicht immer, dass die Aktivität gelöscht wird. Sie gibt an, dass die Aktivität nicht mehr im Vordergrund ist, aber im Mehrfenstermodus weiterhin sichtbar ist. Es gibt mehrere Gründe, warum eine Aktivität in diesen Status wechseln kann:
- Ein Ereignis, das die Ausführung der App unterbricht, wie im Abschnitt zum Callback
onResumebeschrieben, pausiert die aktuelle Aktivität. Dies ist der häufigste Fall. - Im Mehrfenstermodus ist immer nur eine App aktiv und das System pausiert alle anderen Apps.
- Wenn eine neue, halbtransparente Aktivität wie ein Dialogfeld geöffnet wird, wird die Aktivität, die sie abdeckt, pausiert. Solange die Aktivität teilweise sichtbar ist, aber nicht im Fokus steht, bleibt sie pausiert.
Wenn eine Aktivität in den Status „Pausiert“ wechselt, empfängt jede lebenszyklusbewusste Komponente, die an den Lebenszyklus der Aktivität gebunden ist, das Ereignis ON_PAUSE. Hier können die Lebenszykluskomponenten alle Funktionen beenden, die nicht ausgeführt werden müssen, während sich die Komponente nicht im Vordergrund befindet, z. B. die Kameravorschau.
Verwenden Sie die Methode onPause, um Vorgänge zu pausieren oder anzupassen, die nicht fortgesetzt werden können oder die möglicherweise nur eingeschränkt fortgesetzt werden, während sich die Activity im Status „Pausiert“ befindet und die Sie voraussichtlich bald fortsetzen werden.
Sie können die Methode onPause auch verwenden, um Systemressourcen, Handles für Sensoren (z. B. GPS) oder Ressourcen freizugeben, die sich auf die Akkulaufzeit auswirken, während Ihre Aktivität pausiert ist und der Nutzer sie nicht benötigt.
Wie im Abschnitt zu onResume erwähnt, kann eine pausierte Aktivität jedoch weiterhin vollständig sichtbar sein, wenn sich die App im Mehrfenstermodus befindet. Verwenden Sie onStop anstelle von onPause, um UI-bezogene Ressourcen und Vorgänge vollständig freizugeben oder anzupassen, damit der Mehrfenstermodus besser unterstützt wird.
Das folgende Beispiel für eine LifecycleObserver, die auf das Ereignis ON_PAUSE reagiert, ist das Gegenstück zum vorherigen Beispiel für das Ereignis ON_RESUME. Es gibt die Kamera frei, die nach dem Empfang des Ereignisses ON_RESUME initialisiert wird:
class CameraComponent : LifecycleObserver {
...
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
fun releaseCamera() {
camera?.release()
camera = null
}
...
}
In diesem Beispiel wird der Code zum Freigeben der Kamera platziert, nachdem das Ereignis ON_PAUSE von LifecycleObserver empfangen wurde.
Die Ausführung von onPause ist sehr kurz und bietet nicht unbedingt genügend Zeit, um Speichervorgänge auszuführen. Verwenden Sie onPause daher nicht, um Anwendungs- oder Nutzerdaten zu speichern, Netzwerkaufrufe auszuführen oder Datenbanktransaktionen auszuführen.
Diese Arbeit wird möglicherweise nicht abgeschlossen, bevor die Methode abgeschlossen ist.
Führen Sie stattdessen Vorgänge zum Herunterfahren mit hoher Last während onStop aus. Weitere Informationen zu geeigneten Vorgängen, die während onStop ausgeführt werden können, finden Sie im nächsten Abschnitt. Weitere Informationen zum Speichern von Daten finden Sie im Abschnitt Status speichern und wiederherstellen.
Der Abschluss der Methode onPause bedeutet nicht, dass die Aktivität den Status „Pausiert“ verlässt. Stattdessen bleibt die Aktivität in diesem Status, bis sie entweder fortgesetzt wird oder für den Nutzer vollständig unsichtbar wird. Wenn die Aktivität fortgesetzt wird, ruft das System noch einmal den onResume-Callback auf.
Wenn die Aktivität vom Status „Pausiert“ in den Status „Fortgesetzt“ wechselt, behält das System die Activity-Instanz im Arbeitsspeicher und ruft sie auf, wenn das System onResume aufruft. In diesem Szenario müssen Sie Komponenten, die während einer der Callback-Methoden erstellt wurden, die zum Status „Fortgesetzt“ führen, nicht neu initialisieren. Wenn die Aktivität vollständig unsichtbar wird, ruft das System onStop auf.
onStop
Wenn die Aktivität für den Nutzer nicht mehr sichtbar ist, wechselt sie in den Status Beendet und das System ruft den Callback onStop auf. Das kann passieren, wenn eine neu gestartete Aktivität den gesamten Bildschirm einnimmt. Das System ruft onStop auch auf, wenn die Aktivität abgeschlossen ist und beendet wird.
Wenn die Aktivität in den Status „Beendet“ wechselt, empfängt jede lebenszyklusbewusste Komponente, die an den Lebenszyklus der Aktivität gebunden ist, das Ereignis ON_STOP. Hier können die Lebenszykluskomponenten alle Funktionen beenden, die nicht ausgeführt werden müssen, während die Komponente nicht auf dem Bildschirm sichtbar ist.
In der Methode onStop können Sie Ressourcen freigeben oder anpassen, die nicht benötigt werden, während die App für den Nutzer nicht sichtbar ist. Beispielsweise kann Ihre App Animationen pausieren oder von genauen zu ungenauen Standortaktualisierungen wechseln. Wenn du onStop anstelle von onPause verwendest, werden UI-bezogene Aufgaben fortgesetzt, auch wenn der Nutzer deine Aktivität im Mehrfenstermodus ansieht.
Verwenden Sie außerdem onStop, um relativ CPU-intensive Vorgänge zum Herunterfahren auszuführen. Wenn Sie beispielsweise keinen besseren Zeitpunkt finden, um Informationen in einer Datenbank zu speichern, können Sie dies während onStop tun. Das folgende Beispiel zeigt eine Implementierung von onStop, die den Inhalt einer Notiz im Entwurf in einem nichtflüchtigen Speicher speichert:
override fun onStop() {
super.onStop()
// Delegate the save operation to the ViewModel, which handles the
// background thread operations (e.g., using Kotlin Coroutines and Room).
noteViewModel.saveDraft()
}
Wenn deine Aktivität in den Status „Beendet“ wechselt, bleibt das Activity-Objekt im Speicher: Es behält alle Status- und Mitgliedsinformationen bei, ist aber nicht mit dem Window Manager verknüpft. Wenn die Aktivität fortgesetzt wird, werden diese Informationen abgerufen.
Aus dem Status „Beendet“ kehrt die Aktivität entweder zurück, um mit dem Nutzer zu interagieren, oder sie wird beendet und verschwindet. Wenn die Aktivität wieder aktiv wird, ruft das System onRestart auf. Wenn die Ausführung von Activity abgeschlossen ist, ruft das System onDestroy auf.
onDestroy
onDestroy wird aufgerufen, bevor die Aktivität gelöscht wird. Das System ruft diesen Callback aus einem der folgenden Gründe auf:
- Die Aktivität wird beendet, weil der Nutzer die Aktivität vollständig geschlossen hat oder weil
finishfür die Aktivität aufgerufen wurde. - Das System zerstört die Aktivität vorübergehend aufgrund einer Konfigurationsänderung, z. B. wenn das Gerät gedreht oder der Mehrfenstermodus aktiviert wird.
Wenn die Aktivität in den Status „Zerstört“ wechselt, empfängt jede lebenszyklusbewusste Komponente, die an den Lebenszyklus der Aktivität gebunden ist, das Ereignis ON_DESTROY. Hier können die Lebenszykluskomponenten alles bereinigen, was vor dem Löschen der Activity erforderlich ist.
Anstatt Logik in die Activity einzufügen, um zu bestimmen, warum sie zerstört wird, verwenden Sie ein ViewModel-Objekt, das die relevanten Ansichtsdaten für die Activity enthält. Wenn der Activity aufgrund einer Konfigurationsänderung neu erstellt wird, muss der ViewModel nichts tun, da er beibehalten und an die nächste Activity-Instanz übergeben wird.
Wenn die Activity nicht neu erstellt wird, wird für die ViewModel die Methode onCleared aufgerufen, mit der alle erforderlichen Daten bereinigt werden können, bevor sie gelöscht werden. Mit der Methode isFinishing können Sie zwischen diesen beiden Szenarien unterscheiden.
Wenn die Aktivität beendet wird, ist onDestroy der letzte Lebenszyklus-Callback, den die Aktivität erhält. Wenn onDestroy aufgrund einer Konfigurationsänderung aufgerufen wird, erstellt das System sofort eine neue Aktivitätsinstanz und ruft dann onCreate für diese neue Instanz in der neuen Konfiguration auf.
Mit dem Callback onDestroy werden alle Ressourcen freigegeben, die nicht durch frühere Callbacks freigegeben wurden, z. B. onStop.
Aktivitätsstatus und Entfernen aus dem Speicher
Das System beendet Prozesse, wenn es RAM freigeben muss. Die Wahrscheinlichkeit, dass das System einen bestimmten Prozess beendet, hängt vom Status des Prozesses zu diesem Zeitpunkt ab. Der Prozessstatus hängt wiederum vom Status der Aktivität ab, die im Prozess ausgeführt wird. In Tabelle 1 sind die Korrelationen zwischen Prozessstatus, Aktivitätsstatus und der Wahrscheinlichkeit, dass das System den Prozess beendet, aufgeführt. Diese Tabelle gilt nur, wenn ein Prozess keine anderen Arten von Anwendungskomponenten ausführt.
Wahrscheinlichkeit, beendet zu werden |
Prozessstatus |
Endgültiger Aktivitätsstatus |
Niedrigste |
Vordergrund (hat den Fokus oder erhält ihn gleich) |
Fortgesetzt |
Niedrig |
Sichtbar (kein Fokus) |
Gestartet/Pausiert |
Höher |
Hintergrund (unsichtbar) |
Angehalten |
Höchste |
Leer |
Gelöscht |
Tabelle 1: Beziehung zwischen Prozesslebenszyklus und Aktivitätsstatus.
Das System beendet eine Aktivität nie direkt, um Arbeitsspeicher freizugeben. Stattdessen wird der Prozess beendet, in dem die Aktivität ausgeführt wird. Dadurch wird nicht nur die Aktivität, sondern auch alles andere, was im Prozess ausgeführt wird, beendet. Informationen zum Beibehalten und Wiederherstellen des UI-Status Ihrer Aktivität, wenn eine vom System initiierte Prozessbeendigung auftritt, finden Sie im Abschnitt Status speichern und wiederherstellen.
Der Nutzer kann einen Prozess auch beenden, indem er die entsprechende App im Anwendungsmanager unter „Einstellungen“ beendet.
Weitere Informationen zu Prozessen finden Sie unter Prozesse und Threads – Übersicht.
Vorübergehenden UI-Status speichern und wiederherstellen
Nutzer erwarten, dass der UI-Status einer Aktivität während einer Konfigurationsänderung, z. B. einer Drehung oder dem Wechsel in den Mehrfenstermodus, gleich bleibt. Das System zerstört die Aktivität jedoch standardmäßig, wenn eine solche Konfigurationsänderung auftritt, und löscht alle in der Aktivitätsinstanz gespeicherten UI-Zustände.
Ebenso erwarten Nutzer, dass der UI-Status gleich bleibt, wenn sie vorübergehend von deiner App zu einer anderen App wechseln und später zu deiner App zurückkehren. Das System kann jedoch den Prozess deiner App beenden, während der Nutzer abwesend ist und deine Aktivität gestoppt wird.
Wenn die Aktivität aufgrund von Systemeinschränkungen beendet wird, können Sie den vorübergehenden UI-Zustand des Nutzers mit einer Kombination aus ViewModel (für komplexe Geschäftslogik und Bildschirmzustand), der Jetpack Compose API rememberSaveable (für einfachen UI-Zustand) und/oder lokalem Speicher beibehalten. Weitere Informationen zu den Erwartungen der Nutzer im Vergleich zum Systemverhalten und dazu, wie du komplexe UI-Zustandsdaten bei systeminitiierten Aktivitäten und Prozessbeendigungen am besten beibehältst, findest du unter UI-Zustände speichern.
rememberSaveable übersteht automatisch sowohl Konfigurationsänderungen als auch vom System initiierte Prozessbeendigungen, indem der Status im Hintergrund gebündelt wird. So wird eine nahtlose Nutzung ohne Boilerplate-Code auf Aktivitätsebene ermöglicht.
Instanzstatus
Es gibt einige Szenarien, in denen Ihre Activity aufgrund des normalen App-Verhaltens zerstört wird, z. B. wenn der Nutzer den Button „Zurück“ drückt oder Ihre Activity durch Aufrufen der Methode finish ihre eigene Zerstörung signalisiert.
Wenn deine Aktivität gelöscht wird, weil der Nutzer auf „Zurück“ tippt oder die Aktivität sich selbst beendet, ist die Activity-Instanz sowohl für das System als auch für den Nutzer für immer weg. In diesen Szenarien entspricht die Erwartung des Nutzers dem Verhalten des Systems und Sie müssen nichts weiter tun.
Wenn das System die Aktivität jedoch aufgrund von Systemeinschränkungen (z. B. einer Konfigurationsänderung oder Speicherauslastung) zerstört, merkt sich das System, dass die tatsächliche Activity-Instanz vorhanden war, obwohl sie nicht mehr existiert. Wenn der Nutzer versucht, zur Aktivität zurückzukehren, erstellt das System eine neue Instanz dieser Aktivität. Dazu wird ein Satz gespeicherter Daten verwendet, die den Status der Aktivität zum Zeitpunkt ihrer Zerstörung beschreiben.
Die gespeicherten Daten, die das System zum Wiederherstellen des vorherigen Zustands verwendet, werden als Instanzstatus bezeichnet. Im Hintergrund ist es eine Sammlung von Schlüssel/Wert-Paaren. Standardmäßig verwendet das System den Instanzstatus, um grundlegende Informationen zum UI-Layout zu speichern, z. B. Texteingaben von Nutzern oder Scrollpositionen.
Sie können dieses Systemverhalten mit rememberSaveable nutzen. Wenn die Aktivitätsinstanz gelöscht und neu erstellt wird, wird jeder in rememberSaveable verpackte UI-Status automatisch wiederhergestellt, ohne dass Sie zusätzlichen Code auf Aktivitätsebene benötigen.
Deine Aktivität enthält jedoch wahrscheinlich komplexere Statusinformationen, die du wiederherstellen möchtest, z. B. Nutzerdaten, Netzwerkantworten oder Mitgliedsvariablen, die den Fortschritt des Nutzers verfolgen. Der Mechanismus für den Instanzstatus (und damit auch rememberSaveable) ist nicht geeignet, um mehr als eine geringe Menge an Daten zu speichern, da er eine Serialisierung im Hauptthread erfordert und Arbeitsspeicher des Systemprozesses verbraucht.
Wenn Sie mehr als nur eine sehr kleine Datenmenge beibehalten möchten, sollten Sie einen kombinierten Ansatz mit nichtflüchtigem lokalem Speicher, der Klasse ViewModel und Compose-Status-Hoisting verwenden, wie unter UI-Status speichern beschrieben.
Einfachen, einfachen UI-Status mit rememberSaveable speichern
Wenn die Aktivität beendet wird, bereitet das System das Speichern von Statusinformationen in einem Instanzstatus-Bundle vor. Wenn du dieses Systemverhalten nutzen möchtest, verwende rememberSaveable direkt in deinen zusammensetzbaren Funktionen.
rememberSaveable speichert und stellt den vorübergehenden UI-Status, z. B. Texteingaben des Nutzers oder Scrollpositionen, automatisch wieder her, wenn die Aktivität neu erstellt wird.
Wenn Sie benutzerdefinierte, einfache Statusinformationen speichern möchten (z. B. den Fortschritt eines Nutzers in einem Spiel), deklarieren Sie den Status mit rememberSaveable. Das Compose-Framework übernimmt im Hintergrund die Serialisierung in das Instanzstatus-Bundle:
var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) { mutableStateOf( TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length)) ) }
Wenn du persistente Daten wie Nutzereinstellungen oder Daten für eine Datenbank speichern möchtest, solltest du dies tun, wenn deine Aktivität im Vordergrund ist. Wenn sich keine solche Gelegenheit ergibt, speichern Sie persistente Daten während der Methode onStop.
Aktivitäts-UI-Status mithilfe des gespeicherten Instanzstatus wiederherstellen
Wenn Ihre Aktivität nach dem Löschen neu erstellt wird, wird der Status automatisch wiederhergestellt. Wenn Sie rememberSaveable verwenden, müssen Sie keine explizite Wiederherstellungslogik schreiben, keine Null-Bundles prüfen und keine Aktivitäts-Callbacks überschreiben. Der Code, der den Status initialisiert und speichert, stellt ihn auch nahtlos wieder her, wenn die Aktivität fortgesetzt wird:
var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) { mutableStateOf( TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length)) ) }
Aktivitäten und Navigation
Eine App wechselt während ihrer Lebensdauer wahrscheinlich oft zwischen Bildschirmen, z. B. wenn der Nutzer auf den Button „Zurück“ des Geräts tippt oder ein neues Ziel auswählt. Moderne Android-Apps verwenden in der Regel eine Single-Activity-Architektur.
Anstatt für jeden Bildschirm eine neue Activity zu starten, hostet Ihre App eine einzelne Activity und verwendet die Komponente Navigation, um zusammensetzbare Bildschirme innerhalb dieser Aktivität auszutauschen.
Informationen zum Implementieren einer modernen, Compose-orientierten Navigation finden Sie im Leitfaden zur Navigation 3-Bibliothek von Jetpack Compose.
Aktivität aus einer anderen Aktivität starten
Eine Aktivität muss möglicherweise zu einem bestimmten Zeitpunkt eine andere Aktivität starten. Dies ist beispielsweise der Fall, wenn eine App vom aktuellen Bildschirm zu einem neuen wechseln muss.
Je nachdem, ob Ihre Aktivität ein Ergebnis von der neuen Aktivität erwartet, die sie starten möchte, starten Sie die neue Aktivität entweder mit der Methode startActivity oder der Methode startActivityForResult. In beiden Fällen übergeben Sie ein Intent-Objekt.
Das Objekt Intent gibt entweder die genaue Aktivität an, die Sie starten möchten, oder beschreibt die Art der Aktion, die Sie ausführen möchten. Das System wählt die passende Aktivität für Sie aus, die sogar aus einer anderen Anwendung stammen kann. Ein Intent-Objekt kann auch kleine Datenmengen enthalten, die von der gestarteten Aktivität verwendet werden. Weitere Informationen zur Klasse Intent finden Sie unter Intents und Intent-Filter.
startActivity
Wenn die neu gestartete Aktivität kein Ergebnis zurückgeben muss, kann die aktuelle Aktivität sie durch Aufrufen der Methode startActivity starten.
Wenn Sie in Ihrer eigenen Anwendung arbeiten, müssen Sie oft nur eine bekannte Aktivität starten. Das folgende Code-Snippet zeigt beispielsweise, wie eine Aktivität namens SignInActivity gestartet wird.
val context = LocalContext.current
Button(onClick = {
val intent = Intent(context, SignInActivity::class.java)
context.startActivity(intent)
}) {
Text("Sign In")
}
Externe Aktivitäten starten
Die interne App-Navigation wird von Navigation übernommen. Gelegentlich muss Ihre Activity jedoch andere Aktivitäten starten. Das ist in der Regel der Fall, wenn Sie eine externe App verwenden möchten, um eine bestimmte Aktion auszuführen, z. B. einen Webbrowser zu öffnen, eine E-Mail zu senden oder ein Foto aufzunehmen.
Dazu verwenden Sie ein Intent-Objekt, um die Art der Aktion zu beschreiben, die Sie ausführen möchten. Das System startet dann die entsprechende Aktivität aus einer anderen Anwendung.
Wenn Sie dem Nutzer beispielsweise die Möglichkeit geben möchten, eine E‑Mail-Nachricht zu senden, können Sie den folgenden Intent erstellen:
val intent = Intent(Intent.ACTION_SEND).apply {
putExtra(Intent.EXTRA_EMAIL, recipientArray)
}
startActivity(intent)
Wenn Sie eine externe Aktivität starten und ein Ergebnis erhalten möchten (z. B. die Kamera-App auffordern, ein Foto aufzunehmen und das Bild zurückzugeben), verwenden Sie die modernen Activity-Ergebnis-APIs anstelle des verworfenen startActivityForResult-Callbacks.
Aktivitäten koordinieren
Wenn eine Aktivität eine andere startet, durchlaufen beide Lebenszyklusübergänge. Die erste Aktivität wird beendet und wechselt in den Status „Pausiert“ oder „Beendet“, während die andere Aktivität erstellt wird. Wenn diese Aktivitäten Daten gemeinsam nutzen, die auf einem Datenträger oder an einem anderen Ort gespeichert sind, ist es wichtig zu wissen, dass die erste Aktivität nicht vollständig beendet wird, bevor die zweite erstellt wird. Vielmehr überschneidet sich der Prozess des Startens der zweiten Instanz mit dem Prozess des Beendens der ersten Instanz.
Die Reihenfolge der Lebenszyklus-Callbacks ist klar definiert, insbesondere wenn sich die beiden Aktivitäten im selben Prozess befinden, also in derselben App, und eine die andere startet. Hier ist die Reihenfolge der Vorgänge, die auftreten, wenn Aktivität A Aktivität B startet:
- Die Methode
onPausevon Aktivität A wird ausgeführt. - Die Methoden
onCreate,onStartundonResumevon Aktivität B werden nacheinander ausgeführt. Aktivität B hat jetzt den Nutzerfokus. - Wenn Aktivität A nicht mehr auf dem Bildschirm sichtbar ist, wird die Methode
onStopausgeführt.
Mit dieser Abfolge von Lebenszyklus-Callbacks kannst du die Übergabe von Informationen von einer Aktivität an eine andere verwalten.
Zusätzliche Ressourcen
Weitere Informationen zum Aktivitätslebenszyklus finden Sie in den folgenden zusätzlichen Ressourcen: