Wenn ein Nutzer durch Ihre App navigiert, sie 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, mit denen die Aktivität darüber informiert wird, wenn sich ein Status ändert oder das System eine Aktivität erstellt, beendet oder fortsetzt oder den Prozess beendet, in dem sich die Aktivität befindet.
In den Methoden für Lebenszyklus-Callbacks können Sie deklarieren, wie sich Ihre Aktivität verhält, wenn der Nutzer sie verlässt und wieder aufruft. Wenn Sie beispielsweise einen Streaming-Videoplayer 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 Netzwerkverbindung wiederherstellen und dem Nutzer ermöglichen, das Video an derselben Stelle fortzusetzen.
Mit jedem Callback können Sie bestimmte Aufgaben ausführen, die für eine bestimmte Zustandsänderung geeignet sind. Wenn Sie die richtigen Aufgaben zur richtigen Zeit ausführen und Übergänge richtig verarbeiten, wird Ihre App robuster und leistungsfähiger. Eine gute Implementierung der Lebenszyklus-Callbacks kann beispielsweise dazu beitragen, dass Ihre App Folgendes vermeidet:
- Die App stürzt ab, wenn der Nutzer einen Anruf erhält oder zu einer anderen App wechselt, während er Ihre App verwendet.
- Verbrauch wertvoller Systemressourcen, wenn der Nutzer das Gerät nicht aktiv verwendet.
- Der Fortschritt des Nutzers geht verloren, wenn er Ihre App verlässt und später wieder aufruft.
- Die App stürzt ab oder der Fortschritt des Nutzers geht verloren, wenn der Bildschirm zwischen Quer- und Hochformat gedreht wird.
In diesem Dokument wird der Aktivitätslebenszyklus im Detail beschrieben. Das Dokument beginnt mit einer Beschreibung des Lebenszyklusmodells. Anschließend werden die einzelnen Callbacks erläutert: Was passiert intern während der Ausführung und was müssen Sie während der Ausführung implementieren?
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. Abschließend werden mehrere Themen im Zusammenhang mit Übergängen zwischen Aktivitätsstatus behandelt.
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 für den Aktivitätslebenszyklus
Für die Übergänge zwischen den Phasen des Aktivitätslebenszyklus bietet die Klasse Activity eine Reihe von sechs 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 beendet und verbleibt weiterhin im Arbeitsspeicher, z. B. wenn der Nutzer zu einer anderen App wechselt. In diesen Fällen kann die Aktivität weiterhin in den Vordergrund zurückkehren.
Wenn der Nutzer zur Aktivität zurückkehrt, wird sie an der Stelle fortgesetzt, an der er sie verlassen hat. Mit wenigen Ausnahmen dürfen Apps keine Aktivitäten starten, wenn sie im Hintergrund ausgeführt werden.
Die Wahrscheinlichkeit, dass das System einen bestimmten Prozess beendet, hängt vom Status der Aktivität zu diesem Zeitpunkt ab. Weitere Informationen zum Zusammenhang zwischen dem Aktivitätsstatus und der Wahrscheinlichkeit, dass eine App aus dem Arbeitsspeicher entfernt wird, finden Sie im Abschnitt Aktivitätsstatus und Entfernen 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 Nutzer es erwarten.
Compose und der Lebenszyklus
Vermeiden Sie es, Geschäftslogik oder die manuelle Einrichtung von Observers direkt in Aktivitäts-Callbacks wie onStart oder onResume zu platzieren. Verwenden Sie stattdessen lebenszyklusbewusste Effekte und zustandsbewusste Beobachter, die sich automatisch an die Präsenz der Benutzeroberfläche auf dem Bildschirm anpassen.
- Lebenszyklusbezogene Sammlung: Verwenden Sie
collectAsStateWithLifecycle, um Flows aus IhremViewModelzu nutzen. Diese API beginnt automatisch mit der Erfassung, wenn die Benutzeroberfläche in den Status „Started“ wechselt, und wird beendet, wenn sie in den Hintergrund wechselt. So wird unnötiger Ressourcenverbrauch verhindert. Nachdem Sie den Flow als Status erfasst haben, können Sie mitLifecycleEffectsCode ausführen, wenn ein Lifecycle-Ereignis eintritt. - Logikfluss: Durch die Verwendung dieser APIs reagiert die Benutzeroberfläche über den Kompositionsbaum auf natürliche Weise auf den Lebenszyklusstatus. So wird dafür gesorgt, 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 konzeptionelle Informationen und Informationen zur Implementierung der Callback-Methoden, die während des Aktivitätslebenszyklus verwendet werden.
Einige Aktionen gehören zu den Methoden des Aktivitätslebenszyklus. Platzieren Sie den Code, der die Aktionen einer abhängigen Komponente implementiert, jedoch in der Komponente und nicht in der Methode des Aktivitätslebenszyklus. Dazu müssen Sie die abhängige Komponente so gestalten, dass sie den Lebenszyklus berücksichtigt. Informationen dazu, wie Sie Ihre abhängigen Komponenten lebenszyklusbewusst machen, finden Sie unter Lebenszyklus in Jetpack Compose.
onCreate
Sie müssen diesen Callback implementieren, der ausgelöst wird, wenn das System die Aktivität zum ersten Mal erstellt. Nach der Erstellung hat die Aktivität den Status Erstellt. Führen Sie in der Methode onCreate die grundlegende Anwendungsstartlogik aus, die nur einmal für die gesamte Lebensdauer der Aktivität ausgeführt wird.
Ihre Implementierung von onCreate könnte beispielsweise Daten an Listen binden, die Aktivität mit einem ViewModel verknüpfen und einige Variablen im Klassenbereich 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 vorhanden war, ist der Wert des Bundle-Objekts null.
Wenn Sie eine lebenszyklusbewusste Komponente haben, die mit dem Lebenszyklus Ihrer Aktivität verbunden ist, empfängt sie das Ereignis ON_CREATE. Die mit @OnLifecycleEvent annotierte Methode wird aufgerufen, damit Ihre lebenszyklusbewusste Komponente den erforderlichen Einrichtungscode für den erstellten Status ausführen kann.
Das folgende Beispiel zeigt, wie Sie eine Text-Composable in eine einfache Aktivität 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 Ausführung der Methode onCreate abgeschlossen ist, wechselt die Aktivität in den Status Started und das System ruft die Methoden onStart und onResume kurz nacheinander auf.
onStart
Wenn die Aktivität in den Status „Gestartet“ wechselt, ruft das System onStart auf.
Durch diesen Aufruf wird die Aktivität für den Nutzer sichtbar, während die App sich darauf vorbereitet, dass die Aktivität in den Vordergrund wechselt und interaktiv wird. 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 wie beim Status „Created“ bleibt die Aktivität nicht im Status „Started“. Sobald dieser Callback abgeschlossen ist, wechselt die Aktivität in den Status Resumed und das System ruft die Methode onResume auf.
onResume
Wenn die Aktivität in den Status „Resumed“ wechselt, wird sie in den Vordergrund gerückt und das System ruft den onResume-Callback auf. Das ist der Status, in dem die App mit dem Nutzer interagiert. Die App bleibt in diesem Zustand, bis etwas passiert, das den Fokus von der App wegnimmt, z. B. wenn das Gerät einen Anruf empfängt, der Nutzer zu einer anderen Activity wechselt oder das Display des Geräts ausgeschaltet wird.
Wenn die Aktivität in den Status „Fortgesetzt“ wechselt, empfängt jede lebenszyklusbewusste 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 eintritt, wechselt die Aktivität in den Status Pausiert und das System ruft den Callback onPause auf.
Wenn die Aktivität aus dem pausierten in den fortgesetzten Status zurückkehrt, ruft das System die Methode onResume noch einmal auf. Implementieren Sie daher onResume, um Komponenten zu initialisieren, die Sie während onPause freigeben, und um alle anderen Initialisierungen auszuführen, die jedes Mal erfolgen müssen, wenn die Aktivität in den Status „Resumed“ 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()
}
}
...
}
Im vorherigen Code wird die Kamera initialisiert, sobald LifecycleObserver das Ereignis ON_RESUME empfängt. Im Mehrfenstermodus ist Ihre Aktivität jedoch möglicherweise vollständig sichtbar, auch wenn sie pausiert ist. Wenn sich die App beispielsweise im Mehrfenstermodus befindet und der Nutzer auf das Fenster tippt, das Ihre Aktivität nicht enthält, wechselt Ihre 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 oben gezeigten ON_RESUME-Ereignis. Wenn Sie die Kamera aktiv lassen möchten, während die Aktivität pausiert, aber sichtbar ist, z. B. im Mehrfenstermodus, initialisieren Sie die Kamera nach dem ON_START-Ereignis.
Wenn die Kamera jedoch aktiv ist, während Ihre Aktivität pausiert ist, kann dies den Zugriff auf die Kamera für eine andere fortgesetzte App im Mehrfenstermodus verhindern. Manchmal ist es erforderlich, die Kamera aktiv zu lassen, während deine Aktivität pausiert ist. Dies kann jedoch die allgemeine Nutzerfreundlichkeit beeinträchtigen.
Überlegen Sie sich daher genau, an welcher Stelle im Lebenszyklus es am besten ist, die Kontrolle über freigegebene Systemressourcen im Kontext des Mehrfenstermodus 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 die Ressource mit dem entsprechenden Lifecycle-Event freigeben. 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 ON_RESUME-Ereignis initialisieren, geben Sie die Ressource nach dem ON_PAUSE-Ereignis frei.
Im vorherigen Code-Snippet wird der Code zur Kamerainitialisierung in eine lebenszyklusbewusste Komponente eingefügt. Sie können diesen Code stattdessen direkt in die Aktivitätslebenszyklus-Callbacks wie onStart und onStop einfügen. Wir empfehlen dies jedoch nicht. Wenn Sie diese Logik einer unabhängigen, lebenszyklusbewussten Komponente hinzufügen, können Sie die Komponente in mehreren 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 Ihre Aktivität verlässt. Das bedeutet jedoch nicht immer, dass die Aktivität zerstört wird. Sie gibt an, dass die Aktivität nicht mehr im Vordergrund ist, aber weiterhin sichtbar ist, wenn der Nutzer den Mehrfenstermodus verwendet. 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
onResume-Callback beschrieben, pausiert die aktuelle Aktivität. Das ist der häufigste Fall. - Im Mehrfenstermodus hat jeweils nur eine App den Fokus 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, aber nicht im Vordergrund ist, 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 Lifecycle-Komponenten alle Funktionen beenden, die nicht ausgeführt werden müssen, wenn sich die Komponente nicht im Vordergrund befindet, z. B. das Beenden einer Kameravorschau.
Verwenden Sie die Methode onPause, um Vorgänge zu pausieren oder anzupassen, die nicht fortgesetzt werden können oder möglicherweise moderiert fortgesetzt werden, während sich Activity im Status „Pausiert“ befindet und die Sie in Kürze fortsetzen möchten.
Sie können auch die Methode onPause 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 ein LifecycleObserver, das auf das Ereignis ON_PAUSE reagiert, ist das Gegenstück zum vorherigen Beispiel für das Ereignis ON_RESUME. Dabei wird die Kamera freigegeben, 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 Auslösen der Kamera nach dem Empfang des ON_PAUSE-Ereignisses durch LifecycleObserver platziert.
Die Ausführung von onPause ist sehr kurz und bietet nicht unbedingt genügend Zeit für Speichervorgänge. Aus diesem Grund sollten Sie nicht onPause verwenden, um Anwendungs- oder Nutzerdaten zu speichern, Netzwerkaufrufe zu tätigen oder Datenbanktransaktionen auszuführen.
Diese Arbeiten werden möglicherweise nicht abgeschlossen, bevor die Methode abgeschlossen ist.
Führen Sie stattdessen Vorgänge zum Herunterfahren bei hoher Last während onStop aus. Weitere Informationen zu geeigneten Vorgängen während onStop finden Sie im nächsten Abschnitt. Weitere Informationen zum Speichern von Daten finden Sie im Abschnitt Status speichern und wiederherstellen.
Der Abschluss der onPause-Methode bedeutet nicht, dass die Aktivität den Status „Pausiert“ verlässt. Stattdessen bleibt die Aktivität in diesem Status, bis sie fortgesetzt wird oder für den Nutzer vollständig unsichtbar wird. Wenn die Aktivität fortgesetzt wird, ruft das System den onResume-Callback noch einmal auf.
Wenn die Aktivität vom Status „Pausiert“ in den Status „Fortgesetzt“ zurückkehrt, behält das System die Activity-Instanz im Arbeitsspeicher bei und ruft sie wieder auf, wenn das System onResume aufruft. In diesem Fall müssen Sie Komponenten, die während einer der Callback-Methoden bis zum Status „Resumed“ erstellt wurden, nicht neu initialisieren. Wenn die Aktivität vollständig unsichtbar wird, ruft das System onStop auf.
onStop
Wenn deine Aktivität für den Nutzer nicht mehr sichtbar ist, wechselt sie in den Status Beendet und das System ruft den onStop-Callback auf. Das kann passieren, wenn eine neu gestartete Aktivität den gesamten Bildschirm abdeckt. Das System ruft onStop auch auf, wenn die Aktivität beendet wird und kurz vor dem Beenden steht.
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 Lifecycle-Komponenten alle Funktionen beenden, die nicht ausgeführt werden müssen, wenn die Komponente nicht auf dem Bildschirm sichtbar ist.
In der onStop-Methode werden Ressourcen freigegeben oder angepasst, die nicht benötigt werden, während die App für den Nutzer nicht sichtbar ist. Ihre App kann beispielsweise Animationen pausieren oder von detaillierten zu groben Standortaktualisierungen wechseln. Wenn Sie onStop anstelle von onPause verwenden, werden UI-bezogene Aufgaben fortgesetzt, auch wenn der Nutzer Ihre Aktivität im Mehrfenstermodus ansieht.
Verwenden Sie onStop auch für relativ CPU-intensive Herunterfahrvorgänge. Wenn Sie beispielsweise keine bessere Zeit zum Speichern von Informationen in einer Datenbank finden, 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 Ihre Aktivität in den Status „Beendet“ wechselt, bleibt das Activity-Objekt im Arbeitsspeicher: Es behält alle Status- und Mitgliedsinformationen bei, ist aber nicht an den Fenstermanager angehängt. Wenn die Aktivität fortgesetzt wird, werden diese Informationen abgerufen.
Im 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 zurückkehrt, ruft das System onRestart auf. Wenn Activity abgeschlossen ist, ruft das System onDestroy auf.
onDestroy
onDestroy wird aufgerufen, bevor die Aktivität beendet wird. Das System ruft diesen Callback aus einem von zwei Gründen auf:
- Die Aktivität wird beendet, weil der Nutzer sie vollständig schließt oder weil
finishfür die Aktivität aufgerufen wird. - Das System zerstört die Aktivität vorübergehend aufgrund einer Konfigurationsänderung, z. B. wenn das Gerät gedreht wird oder in den Mehrfenstermodus wechselt.
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 sie benötigen, bevor die Activity zerstört wird.
Anstatt Logik in Ihr Activity einzufügen, um zu ermitteln, warum es zerstört wird, verwenden Sie ein ViewModel-Objekt, das die relevanten Ansichtsdaten für Ihr Activity enthält. Wenn die Activity aufgrund einer Konfigurationsänderung neu erstellt wird, muss die ViewModel nichts tun, da sie beibehalten und an die nächste Activity-Instanz übergeben wird.
Wenn die Activity nicht neu erstellt wird, wird die Methode onCleared für die ViewModel aufgerufen, in der alle Daten bereinigt werden können, die vor dem Löschen erforderlich sind. 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 empfängt. Wenn onDestroy als Ergebnis 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 onDestroy-Callback werden alle Ressourcen freigegeben, die nicht von früheren Callbacks wie onStop freigegeben wurden.
Aktivitätsstatus und Entfernen aus dem Speicher
Das System beendet Prozesse, wenn RAM freigegeben werden 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. Tabelle 1 zeigt die Korrelationen zwischen Prozessstatus, Aktivitätsstatus und der Wahrscheinlichkeit, dass das System den Prozess beendet. Diese Tabelle gilt nur, wenn in einem Prozess keine anderen Arten von Anwendungskomponenten ausgeführt werden.
Wahrscheinlichkeit, getötet zu werden |
Prozessstatus |
Endgültiger Aktivitätsstatus |
Niedrigste |
Vordergrund (fokussiert oder kurz davor, fokussiert zu werden) |
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 in diesem Prozess ausgeführt wird, beendet. Informationen dazu, wie Sie den UI-Status Ihrer Aktivität beibehalten und wiederherstellen können, wenn der Prozess vom System beendet wird, finden Sie im Abschnitt zum Speichern und Wiederherstellen des Status.
Der Nutzer kann einen Prozess auch beenden, indem er die entsprechende App über den Anwendungsmanager in den 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-Zustand 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 eintritt, wodurch der in der Aktivitätsinstanz gespeicherte UI-Status gelöscht wird.
Ebenso erwartet ein Nutzer, dass der UI-Status gleich bleibt, wenn er vorübergehend zu einer anderen App wechselt und später zu Ihrer App zurückkehrt. Das System kann den Prozess Ihrer Anwendung jedoch beenden, während der Nutzer nicht da ist und Ihre Aktivität beendet wird.
Wenn Systembeschränkungen die Aktivität beenden, sollten Sie den temporären UI-Status des Nutzers mithilfe einer Kombination aus ViewModel (für komplexe Geschäftslogik und Bildschirmstatus), der Jetpack Compose-API rememberSaveable (für einfachen UI-Status) und/oder dem lokalen Speicher beibehalten. Weitere Informationen zu Nutzererwartungen im Vergleich zum Systemverhalten und dazu, wie Sie komplexe UI-Statusdaten bei vom System initiierten Aktivitäten und Prozessbeendigungen am besten beibehalten, finden Sie unter UI-Status 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 Aktivität aufgrund des normalen App-Verhaltens beendet wird, z. B. wenn der Nutzer die Schaltfläche „Zurück“ drückt oder Ihre Aktivität durch Aufrufen der Methode finish ihr eigenes Beenden signalisiert.
Wenn Ihre Aktivität beendet wird, weil der Nutzer auf „Zurück“ drückt oder die Aktivität selbst beendet wird, ist sowohl das System als auch der Nutzer für immer von dieser Activity-Instanz getrennt. In diesen Szenarien entspricht die Erwartung des Nutzers dem Verhalten des Systems und Sie haben keinen zusätzlichen Aufwand.
Wenn das System die Aktivität jedoch aufgrund von Systembeschränkungen (z. B. einer Konfigurationsänderung oder Speichermangel) beendet, ist die tatsächliche Activity-Instanz zwar nicht mehr vorhanden, das System merkt sich aber, dass sie existiert hat. Wenn der Nutzer versucht, zur Aktivität zurückzukehren, erstellt das System eine neue Instanz dieser Aktivität anhand einer Reihe von gespeicherten Daten, die den Zustand der Aktivität beschreiben, als sie beendet wurde.
Die gespeicherten Daten, die das System zum Wiederherstellen des vorherigen Zustands verwendet, werden als Instanzstatus bezeichnet. Im Grunde ist es eine Sammlung von Schlüssel/Wert-Paaren. Standardmäßig verwendet das System den Instanzstatus, um grundlegende Informationen zu Ihrem UI-Layout zu speichern, z. B. Nutzereingaben oder Scrollpositionen.
Sie können dieses Systemverhalten mit rememberSaveable nutzen. Wenn Ihre Aktivitätsinstanz zerstört und neu erstellt wird, wird der in rememberSaveable eingeschlossene UI-Status automatisch wiederhergestellt. Sie müssen keinen zusätzlichen Code auf Aktivitätsebene schreiben.
Ihre Aktivität enthält jedoch wahrscheinlich komplexere Statusinformationen, die Sie wiederherstellen möchten, 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 triviale Menge an Daten zu speichern, da er die Serialisierung im Hauptthread erfordert und Arbeitsspeicher des Systemprozesses belegt.
Wenn Sie mehr als eine sehr kleine Menge an Daten beibehalten möchten, sollten Sie einen kombinierten Ansatz mit persistentem lokalen Speicher, der Klasse ViewModel und dem Compose-State-Hoisting verwenden, wie unter UI-Zustände speichern beschrieben.
Einfachen, schlanken UI-Status mit „rememberSaveable“ speichern
Wenn Ihre Aktivität beendet wird, bereitet das System das Speichern von Statusinformationen in einem Instanzstatus-Bundle vor. Um dieses Systemverhalten zu nutzen, verwenden Sie rememberSaveable direkt in Ihren zusammensetzbaren Funktionen.
rememberSaveable speichert und stellt den temporären UI-Status, z. B. Nutzereingaben oder Scrollpositionen, bei der Neuerstellung von Aktivitäten automatisch wieder her.
Wenn Sie benutzerdefinierte, einfache Statusinformationen (z. B. den Fortschritt eines Nutzers in einem Spiel) speichern möchten, deklarieren Sie den Status mit rememberSaveable. Das Compose-Framework übernimmt die Serialisierung in das Bundle mit dem Instanzstatus im Hintergrund:
var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) { mutableStateOf( TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length)) ) }
Wenn Sie persistente Daten wie Nutzereinstellungen oder Daten für eine Datenbank speichern möchten, sollten Sie dies tun, wenn Ihre Aktivität im Vordergrund ist. Wenn sich keine solche Möglichkeit ergibt, speichern Sie die persistenten Daten während der onStop-Methode.
UI-Status der Aktivität mithilfe des gespeicherten Instanzstatus wiederherstellen
Wenn Ihre Aktivität nach dem vorherigen Beenden neu erstellt wird, erfolgt die Statuswiederherstellung automatisch. Wenn Sie rememberSaveable verwenden, müssen Sie keine explizite Wiederherstellungslogik schreiben, keine Null-Bundles prüfen und keine Aktivitäts-Callbacks überschreiben. Der Code, mit dem der Status initialisiert und gespeichert wird, stellt ihn auch nahtlos wieder her, wenn die Aktivität zurückkehrt:
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 ihres Lebenszyklus wahrscheinlich mehrmals 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 Architektur mit einer einzelnen Aktivität.
Statt 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-basierten Navigation finden Sie im Leitfaden zur Navigation 3-Bibliothek für Jetpack Compose.
Eine Aktivität über eine andere starten
Eine Aktivität muss möglicherweise irgendwann eine andere Aktivität starten. Dies ist beispielsweise erforderlich, wenn eine App vom aktuellen Bildschirm zu einem neuen wechseln muss.
Je nachdem, ob Ihre Aktivität ein Ergebnis von der neuen Aktivität zurückerhalten soll, die sie starten möchte, starten Sie die neue Aktivität entweder mit der Methode startActivity oder mit der Methode startActivityForResult. In beiden Fällen übergeben Sie ein Intent-Objekt.
Das Intent-Objekt 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 auch 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 häufig 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
Während die interne App-Navigation von Navigation übernommen wird, muss Ihr Activity gelegentlich andere Aktivitäten starten. Das passiert in der Regel, 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 den Typ der auszuführenden Aktion zu beschreiben. Das System startet dann die entsprechende Aktivität aus einer anderen Anwendung.
Wenn Sie dem Nutzer beispielsweise ermöglichen 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 zurückerhalten müssen (z. B. wenn Sie die Kamera-App bitten, ein Foto aufzunehmen und das Bild zurückzugeben), verwenden Sie die modernen Activity-Ergebnis-APIs anstelle des eingestellten 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 der Festplatte 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 des zweiten mit dem Prozess des Beendens des ersten.
Die Reihenfolge der Lebenszyklus-Callbacks ist genau definiert, insbesondere wenn sich die beiden Aktivitäten im selben Prozess befinden, d. h. in derselben App, und eine die andere startet. So läuft es ab, 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 ist jetzt im Fokus des Nutzers. - Wenn Aktivität A nicht mehr auf dem Bildschirm zu sehen ist, wird die Methode
onStopausgeführt.
Mit dieser Sequenz von Lebenszyklus-Callbacks können Sie den Übergang von Informationen von einer Aktivität zur nächsten verwalten.
Zusätzliche Ressourcen
Weitere Informationen zum Aktivitätslebenszyklus finden Sie in den folgenden zusätzlichen Ressourcen: