Einige Gerätekonfigurationen können sich ändern, während die App ausgeführt wird. Dazu gehören unter anderem:
- Anzeigegröße der App
- Bildschirmausrichtung
- Schriftgröße und -stärke
- Sprache
- Dunkler oder heller Modus
- Verfügbarkeit der Tastatur
Die meisten Konfigurationsänderungen sind auf Nutzerinteraktionen zurückzuführen. Wenn du das Gerät beispielsweise drehst oder faltst, ändert sich der für deine App verfügbare Bildschirmplatz. Ebenso werden durch das Ändern von Geräteeinstellungen wie Schriftgröße, Sprache oder bevorzugtes Design die entsprechenden Werte im Configuration
-Objekt geändert.
Diese Parameter erfordern in der Regel ausreichend umfangreiche Änderungen an der Benutzeroberfläche Ihrer App, dass die Android-Plattform über einen speziellen Mechanismus für Änderungen verfügt.
Bei diesem Mechanismus handelt es sich um eine Activity
-Neuerstellung.
Aktivitäten und Freizeitaktivitäten
Bei einer Konfigurationsänderung erstellt das System ein Activity
neu. Dazu ruft das System onDestroy()
auf und löscht die vorhandene Activity
-Instanz. Anschließend wird eine neue Instanz mit onCreate()
erstellt und diese neue Activity
-Instanz wird mit der neuen, aktualisierten Konfiguration initialisiert. Das bedeutet auch, dass das System auch die UI mit der neuen Konfiguration neu erstellt.
Das Verhalten bei der Neuerstellung hilft Ihrer Anwendung, sich an neue Konfigurationen anzupassen. Dazu wird sie automatisch mit alternativen Ressourcen, die der neuen Gerätekonfiguration entsprechen, neu geladen.
Beispiel für Freizeitaktivitäten
Ein Beispiel: TextView
zeigt einen statischen Titel mithilfe von android:text="@string/title"
an, wie in einer Layout-XML-Datei definiert. Wenn die Ansicht erstellt wird, wird der Text basierend auf der aktuellen Sprache genau einmal festgelegt. Wenn sich die Sprache ändert, erstellt das System die Aktivität neu. Daher erstellt das System auch die Ansicht neu und initialisiert sie mit dem richtigen Wert basierend auf der neuen Sprache.
Bei der Neuerstellung werden auch alle Status gelöscht, die als Felder im Activity
oder in einem der darin enthaltenen Fragment
-, View
- oder anderen Objekte beibehalten werden. Das liegt daran, dass bei der Neuerstellung von Activity
eine völlig neue Instanz von Activity
und der UI erstellt wird. Außerdem ist die alte Activity
nicht mehr sichtbar oder gültig, sodass alle verbleibenden Verweise auf sie oder ihre darin enthaltenen Objekte veraltet sind. Sie können Programmfehler, Speicherlecks und Abstürze verursachen.
Erwartungen der Nutzenden
Der Nutzer einer App erwartet, dass der Status beibehalten wird. Wenn ein Nutzer ein Formular ausfüllt und eine andere App im Mehrfenstermodus öffnet, um auf Informationen zu verweisen, beeinträchtigt dies die Nutzerfreundlichkeit, wenn er zu einem gelöschten Formular oder zu einer anderen Stelle in der App zurückkehrt. Als Entwickler müssen Sie durch Konfigurationsänderungen und die Neuerstellung von Aktivitäten für eine einheitliche Nutzererfahrung sorgen.
Wenn Sie prüfen möchten, ob der Status in Ihrer Anwendung erhalten bleibt, können Sie Aktionen ausführen, die zu Konfigurationsänderungen führen, während die Anwendung im Vordergrund und im Hintergrund ausgeführt wird. Diese Aktivitäten umfassen:
- Gerät drehen
- Mehrfenstermodus wird gestartet
- Größenanpassung der Anwendung im Mehrfenstermodus oder in einem Freiformfenster
- Zusammenklappen eines faltbaren Geräts mit mehreren Displays
- Ändern des Systemdesigns, z. B. dunkler oder heller Modus
- Ändern der Schriftgröße
- System- oder App-Sprache ändern
- Hardwaretastatur verbinden oder trennen
- Dock verbinden oder trennen
Es gibt drei primäre Ansätze, mit denen Sie den relevanten Status durch die Neuerstellung von Activity
erhalten können. Welche Version Sie verwenden sollten, hängt von der Art des Status ab, den Sie beibehalten möchten:
- Lokale Persistenz zur Bewältigung von Prozesstod bei komplexen oder großen Daten.
Zum nichtflüchtigen lokalen Speicher gehören Datenbanken oder
DataStore
. - Beibehaltene Objekte wie
ViewModel
-Instanzen zur Verarbeitung von UI-bezogenen Status im Arbeitsspeicher, während der Nutzer die App aktiv verwendet. - Gespeicherter Instanzstatus, um den vom System initiierten Prozessabbruch zu verarbeiten und den vorübergehenden Status beizubehalten, der von der Nutzereingabe oder -navigation abhängt
Weitere Informationen zu den APIs für die einzelnen APIs und deren Verwendung finden Sie unter UI-Status speichern.
Wiederherstellung von Aktivitäten einschränken
Sie können die automatische Wiederherstellung von Aktivitäten bei bestimmten Konfigurationsänderungen verhindern.
Die Neuerstellung von Activity
führt dazu, dass die gesamte UI und alle aus Activity
abgeleiteten Objekte neu erstellt werden. Es gibt gute Gründe, dies zu vermeiden. Beispielsweise kann es sein, dass Ihre Anwendung während einer bestimmten Konfigurationsänderung keine Ressourcen aktualisieren muss oder Sie eine Leistungsbeschränkung haben. In diesem Fall können Sie erklären, dass Ihre Aktivität die Konfigurationsänderung selbst übernimmt, und verhindern, dass das System Ihre Aktivität neu startet.
Wenn Sie die Neuerstellung von Aktivitäten bei bestimmten Konfigurationsänderungen deaktivieren möchten, fügen Sie den Konfigurationstyp in der Datei AndroidManifest.xml
im Eintrag <activity>
zu android:configChanges
hinzu. Mögliche Werte finden Sie in der Dokumentation für das Attribut android:configChanges
.
Mit dem folgenden Manifestcode wird die Neuerstellung von Activity
für MyActivity
deaktiviert, wenn sich die Bildschirmausrichtung und die Tastaturverfügbarkeit ändern:
<activity
android:name=".MyActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:label="@string/app_name">
Einige Konfigurationsänderungen führen immer dazu, dass die Aktivität neu gestartet wird. Sie können sie nicht deaktivieren. Sie können beispielsweise die in Android 12L (API-Level 32) eingeführte dynamische Farbänderung nicht deaktivieren.
Auf Konfigurationsänderungen im View-System reagieren
Bei einer Konfigurationsänderung, für die Sie im View
-System die Neuerstellung von Activity
deaktiviert haben, erhält die Aktivität einen Aufruf an Activity.onConfigurationChanged()
. Alle angehängten Ansichten erhalten auch einen Aufruf von View.onConfigurationChanged()
. Bei Konfigurationsänderungen, die Sie android:configChanges
nicht hinzugefügt haben, erstellt das System die Aktivität wie gewohnt neu.
Die Callback-Methode onConfigurationChanged()
empfängt ein Configuration
-Objekt, das die neue Gerätekonfiguration angibt. Lesen Sie die Felder im Configuration
-Objekt, um Ihre neue Konfiguration zu ermitteln. Aktualisieren Sie die Ressourcen, die Sie in Ihrer Benutzeroberfläche verwenden, um die nachfolgenden Änderungen vorzunehmen. Wenn das System diese Methode aufruft, wird das Resources
-Objekt Ihrer Aktivität so aktualisiert, dass es Ressourcen basierend auf der neuen Konfiguration zurückgibt. So können Sie Elemente Ihrer UI zurücksetzen, ohne dass das System Ihre Aktivität neu startet.
Mit der folgenden onConfigurationChanged()
-Implementierung wird beispielsweise geprüft, ob eine Tastatur verfügbar ist:
Kotlin
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
// Checks whether a keyboard is available
if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_YES) {
Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show()
} else if (newConfig.keyboardHidden === Configuration.KEYBOARDHIDDEN_NO) {
Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show()
}
}
Java
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks whether a keyboard is available
if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_YES) {
Toast.makeText(this, "Keyboard available", Toast.LENGTH_SHORT).show();
} else if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO){
Toast.makeText(this, "No keyboard", Toast.LENGTH_SHORT).show();
}
}
Wenn Sie Ihre Anwendung aufgrund dieser Konfigurationsänderungen nicht aktualisieren müssen, können Sie stattdessen onConfigurationChanged()
nicht implementieren. In diesem Fall werden alle vor der Konfigurationsänderung verwendeten Ressourcen weiterhin verwendet und Sie haben nur den Neustart Ihrer Aktivität vermieden. So kann es z. B. sein, dass eine TV-App nicht reagieren möchte, wenn eine Bluetooth-Tastatur verbunden oder getrennt wird.
Status beibehalten
Bei dieser Methode muss der Zustand während des normalen Aktivitätslebenszyklus beibehalten werden. Das hat folgende Gründe:
- Unvermeidliche Änderungen:Wenn Sie Konfigurationsänderungen nicht verhindern, können Sie Ihre Anwendung neu starten.
- Process Tod:Ihre Anwendung muss in der Lage sein, den vom System initiierten Prozesstod zu verarbeiten. Wenn der Nutzer die Anwendung verlässt und in den Hintergrund geht, wird die App möglicherweise vom System zerstört.
Auf Konfigurationsänderungen in Jetpack Compose reagieren
Mit Jetpack Compose kann Ihre Anwendung leichter auf Konfigurationsänderungen reagieren.
Wenn Sie jedoch die Neuerstellung von Activity
für alle Konfigurationsänderungen deaktivieren, muss Ihre Anwendung Konfigurationsänderungen trotzdem korrekt verarbeiten.
Das Objekt Configuration
ist in der Hierarchie der Erstellungs-UI mit der lokalen Zusammensetzung LocalConfiguration
verfügbar. Bei jeder Änderung werden zusammensetzbare Funktionen, die aus LocalConfiguration.current
lesen, wieder zusammengesetzt. Informationen zur Funktionsweise von Kompositionslokalen finden Sie unter Lokal skalierte Daten mit CompositionLocal.
Beispiel
Im folgenden Beispiel zeigt eine zusammensetzbare Funktion ein Datum in einem bestimmten Format an.
Die zusammensetzbare Funktion reagiert auf Änderungen der Sprachkonfiguration des Systems, indem sie ConfigurationCompat.getLocales()
mit LocalConfiguration.current
aufruft.
@Composable
fun DateText(year: Int, dayOfYear: Int) {
val dateTimeFormatter = DateTimeFormatter.ofPattern(
"MMM dd",
ConfigurationCompat.getLocales(LocalConfiguration.current)[0]
)
Text(
dateTimeFormatter.format(LocalDate.ofYearDay(year, dayOfYear))
)
}
Um zu vermeiden, dass Activity
bei einer Änderung der Sprache neu erstellt wird, muss der Activity
, der den Composer-Code hostet, Änderungen der Sprachkonfiguration deaktivieren. Dazu setzen Sie android:configChanges
auf locale|layoutDirection
.
Konfigurationsänderungen: Schlüsselkonzepte und Best Practices
Dies sind die wichtigsten Konzepte, die Sie bei der Arbeit an Konfigurationsänderungen kennen sollten:
- Konfigurationen:Gerätekonfigurationen legen fest, wie die Benutzeroberfläche dem Nutzer angezeigt wird, z. B. Anzeigegröße der App, Sprache oder Systemdesign.
- Konfigurationsänderungen:Konfigurationen ändern sich durch Nutzerinteraktionen. Der Nutzer kann beispielsweise die Geräteeinstellungen oder die physische Interaktion mit dem Gerät ändern. Es gibt keine Möglichkeit, Konfigurationsänderungen zu verhindern.
- Neuerstellung von
Activity
: Konfigurationsänderungen führen standardmäßig zur Neuerstellung vonActivity
. Dies ist ein integrierter Mechanismus, mit dem der App-Status für die neue Konfiguration neu initialisiert wird. - Löschen
Activity
: Bei der Neuerstellung vonActivity
löscht das System die alteActivity
-Instanz und erstellt stattdessen eine neue. Die alte Instanz ist jetzt veraltet. Alle verbleibenden Verweise darauf führen zu Speicherlecks, Programmfehlern oder Abstürzen. - Status: Der Status in der alten
Activity
-Instanz ist in der neuenActivity
-Instanz nicht vorhanden, da es sich um zwei verschiedene Objektinstanzen handelt. Sie können die App und den Nutzerstatus wie unter UI-Status speichern beschrieben beibehalten. - Deaktivieren:Eine mögliche Optimierung ist das Deaktivieren der Neuerstellung von Aktivitäten für eine Art von Konfigurationsänderung. Ihre Anwendung muss als Reaktion auf die neue Konfiguration ordnungsgemäß aktualisiert werden.
Beachten Sie die folgenden Best Practices, um eine gute Nutzererfahrung zu bieten:
- Auf häufige Konfigurationsänderungen vorbereitet sein:Sie sollten nicht davon ausgehen, dass Konfigurationsänderungen selten oder nie auftreten, unabhängig von API-Ebene, Formfaktor oder UI-Toolkit. Wenn ein Nutzer eine Konfigurationsänderung verursacht, erwartet er, dass Apps aktualisiert werden und weiterhin korrekt mit der neuen Konfiguration funktionieren.
- Status beibehalten: Der Status des Nutzers wird nicht verloren, wenn eine
Activity
-Neuerstellung durchgeführt wird. Behalten Sie den Status wie unter UI-Zustände speichern beschrieben bei. - Deaktivieren Sie die Funktion nicht als schnelle Lösung:Deaktivieren Sie nicht die Neuerstellung von
Activity
als Verknüpfung, um einen Verlust des Status zu vermeiden. Wenn du die Wiederherstellung von Aktivitäten deaktivierst, musst du das Versprechen zur Verarbeitung der Änderung einhalten. Du kannst den Status trotzdem verlieren, wennActivity
aus anderen Konfigurationsänderungen wiederhergestellt, der Tod verarbeitet oder die App geschlossen wird. Es ist nicht möglich, die Neuerstellung vonActivity
vollständig zu deaktivieren. Behalten Sie den Status wie unter UI-Zustände speichern beschrieben bei. - Vermeiden Sie keine Konfigurationsänderungen: Schränken Sie die Ausrichtung, das Seitenverhältnis oder die Größe nicht ein, um Konfigurationsänderungen und die Neuerstellung von
Activity
zu vermeiden. Das wirkt sich negativ auf Nutzer aus, die Ihre App in ihrer bevorzugten Art verwenden möchten.
Größenbasierte Konfigurationsänderungen verarbeiten
Größenbasierte Konfigurationsänderungen können jederzeit vorgenommen werden. Die Wahrscheinlichkeit ist größer, wenn Ihre App auf einem Gerät mit großen Bildschirmen ausgeführt wird, auf dem Nutzer in den Mehrfenstermodus wechseln können. Er erwartet, dass Ihre Anwendung in dieser Umgebung gut funktioniert.
Es gibt zwei allgemeine Arten von Größenänderungen: signifikant und unbedeutend. Bei einer erheblichen Größenänderung gilt eine andere Gruppe alternativer Ressourcen für die neue Konfiguration, da sich die Bildschirmgröße unterscheidet, z. B. Breite, Höhe oder kleinste Breite. Zu diesen Ressourcen gehören Ressourcen, die von der App selbst definiert wurden, sowie Ressourcen, die aus ihren Bibliotheken stammen.
Neuerstellung von Aktivitäten für größenbasierte Konfigurationsänderungen einschränken
Wenn Sie die Activity
-Neuerstellung für größenbasierte Konfigurationsänderungen deaktivieren, wird die Activity
nicht neu erstellt. Stattdessen wird ein Aufruf von Activity.onConfigurationChanged()
empfangen. Alle angehängten Ansichten erhalten einen Aufruf von View.onConfigurationChanged()
.
Die Neuerstellung von Activity
ist für größenbasierte Konfigurationsänderungen deaktiviert, wenn Ihre Manifestdatei android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout
enthält.
Neuerstellung von Aktivitäten für größenbasierte Konfigurationsänderungen zulassen
Unter Android 7.0 (API-Level 24) und höher erfolgt die Activity
-Neuerstellung nur bei größenbasierten Konfigurationsänderungen, wenn die Größenänderung erheblich ist. Wenn das System aufgrund unzureichender Größe keine neue Activity
erstellt, ruft das System stattdessen möglicherweise Activity.onConfigurationChanged()
und View.onConfigurationChanged()
auf.
Es gibt einige Einschränkungen in Bezug auf die Activity
- und View
-Callbacks, wenn Activity
nicht neu erstellt wird:
- Unter Android 11 (API-Level 30) bis Android 13 (API-Level 33) wird
Activity.onConfigurationChanged()
nicht aufgerufen. - Es gibt ein bekanntes Problem, bei dem
View.onConfigurationChanged()
in einigen Fällen unter Android 12L (API-Level 32) und frühen Versionen von Android 13 (API-Level 33) möglicherweise nicht aufgerufen wird. Weitere Informationen finden Sie in dieser öffentlichen Ausgabe. In späteren Releases von Android 13 und Android 14 wurde dieses Problem inzwischen behoben.
Für Code, der auf größenbasierte Konfigurationsänderungen warten muss, empfehlen wir die Verwendung eines Dienstprogramms View
mit einem überschriebenen View.onConfigurationChanged()
, anstatt eine Activity
-Neuerstellung oder Activity.onConfigurationChanged()
zu verwenden.