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 Modus im Vergleich zum hellen Modus
- Verfügbarkeit der Tastatur
Die meisten dieser Konfigurationsänderungen sind auf eine Nutzerinteraktion zurückzuführen. Wenn Sie beispielsweise das Gerät drehen oder zusammenklappen, ändert sich der für Ihre App verfügbare Bildschirmplatz. Wenn Sie Geräteeinstellungen wie die Schriftgröße, die Sprache oder das bevorzugte Design ändern, ändern sich auch die entsprechenden Werte im Configuration-Objekt.
Diese Parameter erfordern in der Regel so große Änderungen an der Benutzeroberfläche Ihrer Anwendung, dass die Android-Plattform einen speziell entwickelten Mechanismus für den Fall hat, dass sie sich ändern.
Dieser Mechanismus ist die Neuerstellung von Activity.
Neuerstellung von `Activity`
Das System erstellt eine Activity neu, wenn eine Konfigurationsänderung auftritt. Dazu ruft das System onDestroy auf und zerstört die vorhandene Activity
Instanz. Anschließend wird mit onCreate eine neue Instanz erstellt. Diese neue
Activity Instanz wird mit der neuen, aktualisierten Konfiguration initialisiert. Das bedeutet auch, dass das System die Benutzeroberfläche mit der neuen Konfiguration neu erstellt.
In der Regel fungiert die Activity als Host für Composables. Wenn die Activity neu erstellt wird, erstellt Compose auch die Benutzeroberfläche mit den neuen Konfigurationswerten neu.
Durch das Neuerstellungsverhalten kann sich Ihre Anwendung an neue Konfigurationen anpassen, indem sie automatisch mit alternativen Ressourcen neu geladen wird, die der neuen Gerätekonfiguration entsprechen.
Beispiel für die Neuerstellung
Stellen Sie sich ein Composable vor, das einen statischen Titel mit einer String-Ressource anzeigt:
// In the res/values/strings.xml file // <string name="compose">Jetpack Compose</string> // In your Compose code Text( text = stringResource(R.string.compose) )
Wenn die Activity erstellt wird, liest das Text-Composable die aktuelle Konfiguration (z. B. die Sprache) und löst die entsprechende String-Ressource auf.
Wenn sich die Sprache ändert, erstellt das System die Aktivität neu. In diesem Fall erstellt Compose die Benutzeroberfläche neu. Da stringResource aus der aktuellen Konfiguration liest, wird der Titel automatisch auf den richtigen lokalisierten Wert aktualisiert.
Bei der Neuerstellung wird auch der gesamte Status gelöscht, der als Felder in der Activity gespeichert ist.
Wenn Sie den UI-Status bei Konfigurationsänderungen beibehalten möchten, verwenden Sie die empfohlenen Muster für die Statusverwaltung. Verwenden Sie ViewModel für Daten und Geschäftslogik und rememberSaveable für den Status auf UI-Ebene. Mit diesen Mechanismen bleibt der Status bei der Neuerstellung von Activity erhalten, während die Benutzeroberfläche aktualisiert wird, um die neue Konfiguration widerzuspiegeln.
Weitere Informationen zum Speichern des Status in Compose finden Sie unter UI-Status in Compose speichern.
Erwartungen der Nutzer
Nutzer einer App erwarten, dass der Status beibehalten wird. Wenn ein Nutzer ein Formular ausfüllt und im Mehrfenstermodus eine andere App öffnet, um Informationen nachzuschlagen, ist es schlecht für die Nutzererfahrung, wenn er zu einem leeren Formular oder an eine ganz andere Stelle in der App zurückkehrt. Als Entwickler müssen Sie bei Konfigurationsänderungen und der Neuerstellung von Aktivitäten eine konsistente Nutzererfahrung bieten.
Um zu prüfen, ob der Status in Ihrer Anwendung beibehalten wird, können Sie Aktionen ausführen, die Konfigurationsänderungen verursachen, sowohl wenn sich die App im Vordergrund als auch im Hintergrund befindet. Diese Aktivitäten umfassen:
- Drehen des Geräts
- Starten des Mehrfenstermodus
- Ändern der Größe der Anwendung im Mehrfenstermodus oder in einem Freiform-Fenster
- Zusammenklappen eines faltbaren Geräts mit mehreren Displays
- Ändern des Systemdesigns, z. B. vom dunklen in den hellen Modus
- Ändern der Schriftgröße
- Ändern der System- oder App-Sprache
- Verbinden oder Trennen einer Hardwaretastatur
- Verbinden oder Trennen einer Dockingstation
Es gibt mehrere Möglichkeiten, den relevanten Status bei der Neuerstellung von Activity beizubehalten. Welche Methode Sie verwenden, hängt vom Typ des Status ab, den Sie beibehalten möchten:
- Lokale Persistenz zur Verarbeitung von Prozessbeendigung bei komplexen oder großen Daten.
Permanenter lokaler Speicher umfasst Datenbanken oder
DataStore. - Beibehaltene Objekte wie
ViewModel-Instanzen zur Verarbeitung des UI-bezogenen Status im Arbeitsspeicher, während der Nutzer die App aktiv verwendet. rememberSaveablezum Beibehalten des temporären UI-Status bei Konfigurationsänderungen und systemseitiger Prozessbeendigung. Dies ist für Status geeignet, der von der Nutzereingabe, der Scrollposition oder der Navigation abhängt, aber nicht in eineViewModelgehört.
Informationen zu den APIs für die einzelnen Methoden und wann die Verwendung der jeweiligen Methode geeignet ist, finden Sie unter UI-Status speichern.
Neuerstellung von Aktivitäten einschränken
Sie können die automatische Neuerstellung von Aktivitäten für bestimmte Konfigurationsänderungen verhindern. In modernen Apps, die nur Compose verwenden, wird die Benutzeroberfläche so oder so neu zusammengesetzt. Es wird jedoch empfohlen, die Konfigurationsänderung direkt zu verarbeiten.
Standardmäßig führt eine Konfigurationsänderung dazu, dass das System die Aktivität zerstört und neu erstellt, einschließlich der Benutzeroberfläche und aller Objekte, die von der Aktivität abgeleitet wurden. Wenn Sie deklarieren, dass Ihre Aktivität die Konfigurationsänderung selbst verarbeitet, verhindert das System dies. Stattdessen wird nur das Configuration-Objekt aktualisiert und Compose setzt die Benutzeroberfläche mit den neuen Werten neu zusammen.
Die direkte Verarbeitung von Konfigurationsänderungen in Compose hat mehrere Vorteile:
- Verbesserte Leistung:Das Neuzusammensetzen der Benutzeroberfläche ist weniger aufwendig als ein vollständiger Neuerstellungszyklus für Aktivitäten, insbesondere bei kleineren Änderungen.
- Flüssige Animationen:Wenn Sie einen Neustart der Aktivität vermeiden, können Sie kontinuierliche Animationen bei Konfigurationsänderungen ausführen, z. B. reibungslose Layoutübergänge beim Drehen des Geräts.
- Statusbeibehaltung:Durch das Beibehalten der Aktivitätsinstanz wird das Risiko eines Verlusts des temporären UI-Status bei einem Ereignis wie dem Drehen des Bildschirms verringert. Sie müssen jedoch weiterhin die Statusbeibehaltung für die systemseitige Prozessbeendigung verarbeiten.
Wenn Sie die Neuerstellung von Aktivitäten für bestimmte Konfigurationsänderungen deaktivieren möchten,
fügen Sie den Konfigurationstyp in der
<activity> Datei im Eintrag android:configChanges zu AndroidManifest.xml hinzu. Mögliche Werte
finden Sie in der Dokumentation für das android:configChanges Attribut.
Der folgende Manifestcode deaktiviert die Neuerstellung von Activity für MyActivity, wenn
sich die Bildschirmausrichtung und die Verfügbarkeit der Tastatur ändern:
<activity
android:name=".MyActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:label="@string/app_name">
Android 17
Ab Android 17 (API-Level 37) startet das System Aktivitäten nicht mehr standardmäßig für mehrere Konfigurationsänderungen neu, die in der Regel keine vollständige Neuerstellung der Benutzeroberfläche erfordern.
Stattdessen bleiben Aktivitäten aktiv und erhalten Updates über den
onConfigurationChanged()-Callback.
Zu den spezifischen Konfigurationsänderungen gehören:
CONFIG_KEYBOARDCONFIG_KEYBOARD_HIDDENCONFIG_NAVIGATIONCONFIG_TOUCHSCREENCONFIG_COLOR_MODECONFIG_UI_MODE(nur wenn sich der UI-Modus inUI_MODE_TYPE_DESKändert oder vonUI_MODE_TYPE_DESKzu einem anderen Typ)
Wenn Ihre Anwendung auf einem vollständigen Neustart basiert, um Ressourcen für diese
Änderungen neu zu laden, müssen Sie sich jetzt explizit für das alte Verhalten entscheiden, indem Sie das
android:recreateOnConfigChanges Attribut in der Manifestdatei verwenden.
Mit dem Attribut können Sie angeben, welche Konfigurationsänderungen einen vollständigen Stopp, die Zerstörung und die Neuerstellung der Aktivität auslösen sollen, z. B.:
<activity
android:name=".MyActivity"
android:recreateOnConfigChanges="keyboard|keyboardHidden|navigation|colorMode|touchscreen|...">
...
</activity>
Auf Konfigurationsänderungen reagieren
Mit Jetpack Compose kann Ihre App einfacher auf Konfigurationsänderungen reagieren.
Wenn Sie jedoch die Neuerstellung von Activity für alle Konfigurationsänderungen deaktivieren, bei denen dies möglich ist, muss Ihre App Konfigurationsänderungen weiterhin korrekt verarbeiten.
Das Configuration-Objekt ist in der Compose-UI-Hierarchie mit
dem lokalen LocalConfiguration-Composable verfügbar. Wenn es sich ändert, werden Composable-Funktionen, die aus LocalConfiguration.current lesen, neu zusammengesetzt. Informationen zur Funktionsweise von lokalen Composables finden Sie unter Daten mit lokalem Gültigkeitsbereich mit CompositionLocal.
Beispiel
Im folgenden Beispiel zeigt ein Composable ein Datum in einem bestimmten Format an.
Das Composable reagiert auf Konfigurationsänderungen des Systemgebietsschemas, indem es
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 die Neuerstellung von Activity zu vermeiden, wenn sich das Gebietsschema ändert, muss die Activity, die den Compose-Code hostet, die Konfigurationsänderungen des Gebietsschemas deaktivieren. Dazu legen Sie android:configChanges auf locale|layoutDirection fest.
Konfigurationsänderungen: Wichtige Konzepte und Best Practices
Das sind die wichtigsten Konzepte, die Sie bei der Arbeit an Konfigurationsänderungen kennen müssen:
- Konfigurationen:Gerätekonfigurationen definieren, wie die Benutzeroberfläche für den Nutzer angezeigt wird, z. B. die Anzeigegröße der App, die Sprache oder das Systemdesign. In Compose können Sie mit
LocalConfigurationauf Konfigurationswerte zugreifen. - Konfigurationsänderungen:Konfigurationen ändern sich durch Nutzerinteraktionen. Der Nutzer kann beispielsweise Geräteeinstellungen ändern oder auf andere Weise mit dem Gerät interagieren. 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, um den App-Status für die neue Konfiguration neu zu initialisieren. - Zerstörung von
Activity:Bei der Neuerstellung vonActivitywird die alteActivity-Instanz vom System zerstört und an ihrer Stelle eine neue erstellt. Die alte Instanz ist jetzt veraltet. Vermeiden Sie es, Verweise auf Objekte mit Lebenszyklusbereich über den vorgesehenen Bereich hinaus beizubehalten. - Status:Der Status in der alten
Activity-Instanz ist in der neuenActivity-Instanz nicht vorhanden, da es sich um zwei verschiedene Objektinstanzen handelt. Anstatt den Status an die Aktivität zu binden, verwenden Sie die empfohlenen APIs, um den Status der App und des Nutzers beizubehalten, wie unter UI-Status speichern beschrieben. - Deaktivieren:Wenn Sie die Neuerstellung von Aktivitäten für eine Art von Konfigurationsänderung deaktivieren, muss Ihre App 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:Gehen Sie nicht davon aus, dass Konfigurationsänderungen selten oder nie auftreten, unabhängig von API-Level, Formfaktor oder UI-Toolkit. Wenn ein Nutzer eine Konfigurationsänderung verursacht, erwartet er, dass Apps aktualisiert werden und mit der neuen Konfiguration weiterhin korrekt funktionieren.
- Status beibehalten:Der Status des Nutzers darf bei der Neuerstellung von
Activitynicht verloren gehen. Behalten Sie den Status wie unter UI-Status speichern beschrieben mit APIs wieViewModelundrememberSaveablebei. - Deaktivieren nicht als schnelle Lösung verwenden:Deaktivieren Sie die Neuerstellung von
Activitynicht als Abkürzung, um Statusverluste zu vermeiden. Wenn Sie die Neuerstellung von Aktivitäten deaktivieren, müssen Sie die Änderung verarbeiten. Außerdem kann der Status aufgrund der Neuerstellung vonActivitydurch andere Konfigurationsänderungen, Prozessbeendigung oder Schließen der App verloren gehen. Es ist nicht möglich, die Neuerstellung vonActivityvollständig zu deaktivieren. Behalten Sie den Status wie unter UI-Status speichern beschrieben bei. - Konfigurationsänderungen nicht vermeiden: Beschränken Sie nicht die Ausrichtung,
das Seitenverhältnis oder die Größenänderung, um Konfigurationsänderungen und
ActivityNeuerstellung zu vermeiden. Dies wirkt sich negativ auf Nutzer aus, die Ihre App auf die von ihnen bevorzugte Weise verwenden möchten.
Größenbasierte Konfigurationsänderungen verarbeiten
Größenbasierte Konfigurationsänderungen können jederzeit auftreten und sind wahrscheinlicher wenn Ihre App auf einem Gerät mit großem Bildschirm ausgeführt wird, auf dem Nutzer den Mehrfenstermodus starten können. Sie erwarten, dass Ihre App in dieser Umgebung gut funktioniert.
Es gibt zwei allgemeine Arten von Größenänderungen: bedeutende und unbedeutende. Eine bedeutende Größenänderung ist eine Änderung, bei der aufgrund eines Unterschieds in der Bildschirmgröße, z. B. Breite, Höhe oder kleinste Breite, ein anderer Satz alternativer Ressourcen auf die neue Konfiguration angewendet wird. Zu diesen Ressourcen gehören sowohl die von der App selbst definierten als auch die aus ihren Bibliotheken.
Neuerstellung von Aktivitäten für größenbasierte Konfigurationsänderungen einschränken
Wenn Sie die Neuerstellung von Activity für größenbasierte Konfigurationsänderungen deaktivieren, wird die Activity nicht neu erstellt. Stattdessen wird
Activity.onConfigurationChanged aufgerufen. Alle Composables, die LocalConfiguration.current lesen, werden automatisch neu zusammengesetzt, um die neue Größe widerzuspiegeln.
Activity recreation is disabled for size-based configuration changes when
you have
android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout"
in your manifest file.
Zusätzliche Ressourcen
Weitere Informationen zum Umgang mit Konfigurationsänderungen finden Sie in den folgenden zusätzlichen Ressourcen: