Einige Gerätekonfigurationen können sich ändern, während die App ausgeführt wird. Dazu gehören unter anderem:
- App-Anzeigegröße
- Bildschirmausrichtung
- Schriftgröße und ‑stärke
- Sprache
- Dunkler Modus im Vergleich zum hellen Modus
- Verfügbarkeit der Tastatur
Die meisten dieser Konfigurationsänderungen werden durch Nutzerinteraktionen ausgelöst. Wenn das Gerät beispielsweise gedreht oder zusammengeklappt wird, ändert sich die Menge an Bildschirmplatz, die für Ihre App verfügbar ist. Wenn Geräteeinstellungen wie Schriftgröße, Sprache oder bevorzugtes Design geändert werden, ä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 Activity-Neuerstellung.
Aktivitätserholung
Das System erstellt ein Activity neu, wenn eine Konfigurationsänderung erfolgt. 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.
Normalerweise fungiert das Activity als Host für Composables. Wenn Activity neu erstellt wird, wird auch die Benutzeroberfläche mit den neuen Konfigurationswerten neu erstellt.
Durch das Verhalten beim Neuerstellen 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 Freizeit
Stellen Sie sich eine Compose-Funktion vor, die 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 die zusammensetzbare Text die aktuelle Konfiguration (z. B. die Sprache) und löst die entsprechende String-Ressource auf.
Wenn sich die Sprache ändert, wird die Aktivität vom System neu erstellt. In diesem Fall wird die Benutzeroberfläche von Compose neu erstellt. Da stringResource aus der aktuellen Konfiguration gelesen wird, 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.
Verwenden Sie empfohlene Muster für die Statusverwaltung, um den UI-Status bei Konfigurationsänderungen beizubehalten. Verwenden Sie ViewModel für Daten und Geschäftslogik und rememberSaveable für den Status auf UI-Ebene. Durch diese 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 erwarten, dass der Status einer App beibehalten wird. Wenn ein Nutzer ein Formular ausfüllt und eine andere App im Mehrfenstermodus öffnet, um Informationen abzurufen, ist es schlecht für die Nutzerfreundlichkeit, wenn er zu einem leeren Formular oder zu einer ganz anderen Stelle in der App zurückkehrt. Als Entwickler müssen Sie bei Konfigurationsänderungen und der Neuerstellung von Aktivitäten für eine einheitliche Nutzererfahrung sorgen.
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:
- Gerät drehen
- Mehrfenstermodus starten
- Größe der Anwendung im Mehrfenstermodus oder in einem Freiform-Fenster ändern
- Ein Foldable mit mehreren Displays zusammenfalten
- Das Systemdesign ändern, z. B. vom dunklen zum hellen Modus wechseln
- Schriftgröße ändern
- System- oder App-Sprache ändern
- Hardwaretastatur anschließen oder trennen
- Dockingstation anschließen oder trennen
Es gibt verschiedene Möglichkeiten, 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, um das Beenden von Prozessen bei komplexen oder großen Daten zu verarbeiten.
Die dauerhafte lokale Speicherung umfasst Datenbanken oder
DataStore. - Beibehaltene Objekte wie
ViewModel-Instanzen, um UI-bezogene Status im Arbeitsspeicher zu verarbeiten, während der Nutzer die App aktiv verwendet. rememberSaveable, um den vorübergehenden UI-Status bei Konfigurationsänderungen und vom System initiierten Prozessbeendigungen beizubehalten. Das ist für Status geeignet, die von Nutzereingaben, der Scrollposition oder der Navigation abhängen, aber nicht in eineViewModelgehören.
Weitere Informationen zu den APIs für die einzelnen Fälle und dazu, wann die Verwendung der jeweiligen API angemessen ist, finden Sie unter UI-Zustände speichern.
Erstellung von Aktivitäten einschränken
Sie können verhindern, dass Aktivitäten bei bestimmten Konfigurationsänderungen automatisch neu erstellt werden. In modernen reinen Compose-Apps wird die Benutzeroberfläche ohnehin neu zusammengesetzt. Es wird jedoch empfohlen, die Konfigurationsänderung direkt zu verarbeiten.
Standardmäßig zwingt eine Konfigurationsänderung das System, die Activity zu löschen und neu zu erstellen, einschließlich der Benutzeroberfläche und aller Objekte, die von der Activity abgeleitet sind. 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 rendert die Benutzeroberfläche mit den neuen Werten neu.
Die direkte Verarbeitung von Konfigurationsänderungen in Compose bietet mehrere Vorteile:
- Verbesserte Leistung:Das Neuzusammenstellen der Benutzeroberfläche ist weniger aufwendig als ein vollständiger Zyklus zum Neuerstellen einer Aktivität, 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.
- Status beibehalten:Wenn die Activity-Instanz beibehalten wird, sinkt das Risiko, dass der temporäre UI-Status bei einem Ereignis wie der Bildschirmdrehung verloren geht. Beachten Sie, dass Sie die Statusbeibehaltung für vom System initiierte Prozessbeendigungen weiterhin selbst verarbeiten müssen.
Wenn Sie die Neuerstellung von Aktivitäten für bestimmte Konfigurationsänderungen deaktivieren möchten, fügen Sie den Konfigurationstyp in der AndroidManifest.xml-Datei dem Eintrag <activity> in 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 Verfügbarkeit der Tastatur ändern:
<activity
android:name=".MyActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:label="@string/app_name">
Auf Konfigurationsänderungen reagieren
Mit Jetpack Compose kann Ihre App leichter auf Konfigurationsänderungen reagieren. Wenn Sie die Neuerstellung von Activity für alle Konfigurationsänderungen deaktivieren, bei denen dies möglich ist, muss Ihre App Konfigurationsänderungen dennoch korrekt verarbeiten.
Das Configuration-Objekt ist in der Compose-UI-Hierarchie mit dem Kompositionslokal LocalConfiguration verfügbar. Wenn es sich ändert, werden Kompositionsfunktionen, die LocalConfiguration.current lesen, neu zusammengesetzt. Weitere Informationen zur Funktionsweise von Kompositionslokalen finden Sie unter Lokal begrenzte Daten mit CompositionLocal.
Beispiel
Im folgenden Beispiel wird in einem Composable-Element ein Datum in einem bestimmten Format angezeigt. Das Composable-Element reagiert auf Änderungen der Systemgebietsschema-Konfiguration, indem ConfigurationCompat.getLocales mit LocalConfiguration.current aufgerufen wird.
@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))
)
}
Damit Activity nicht neu erstellt wird, wenn sich das Gebietsschema ändert, muss das Activity, in dem der Compose-Code gehostet wird, die Änderungen der Gebietsschemakonfiguration deaktivieren. Legen Sie dazu android:configChanges auf locale|layoutDirection fest.
Konfigurationsänderungen: Wichtige Konzepte und Best Practices
Dies sind die wichtigsten Konzepte, die Sie bei der Arbeit an Konfigurationsänderungen kennen sollten:
- 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 ändert beispielsweise die Geräteeinstellungen oder die Art und Weise, wie er das Gerät physisch bedient. Konfigurationsänderungen lassen sich nicht verhindern.
Activityneu erstellen:Konfigurationsänderungen führen standardmäßig dazu, dassActivityneu erstellt wird. Dies ist ein integrierter Mechanismus zum Re-Initialisieren des App-Status für die neue Konfiguration.Activity-Zerstörung:Wenn eineActivity-Instanz neu erstellt wird, wird die alteActivity-Instanz zerstört und an ihrer Stelle eine neue erstellt. Die alte Instanz ist jetzt obsolet. 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, sollten Sie die empfohlenen APIs verwenden, 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 ordnungsgemäß auf die neue Konfiguration reagieren.
Für eine gute Nutzererfahrung sollten Sie die folgenden Best Practices beachten:
- Häufige Konfigurationsänderungen einplanen:Gehen Sie nicht davon aus, dass Konfigurationsänderungen selten oder nie vorkommen, unabhängig von API-Level, Formfaktor oder UI-Toolkit. Wenn ein Nutzer eine Konfigurationsänderung vornimmt, erwartet er, dass Apps aktualisiert werden und mit der neuen Konfiguration weiterhin korrekt funktionieren.
- Status beibehalten:Der Status des Nutzers darf nicht verloren gehen, wenn
Activityneu erstellt wird. Speichern Sie den Status wie unter UI-Status speichern beschrieben mithilfe von APIs wieViewModelundrememberSaveable. - Vermeiden Sie das Deaktivieren als schnelle Lösung:Deaktivieren Sie das Neuerstellen von
Activitynicht als Abkürzung, um den Verlust des Status zu vermeiden. Wenn Sie das Neuerstellen von Aktivitäten deaktivieren, müssen Sie die Änderung wie versprochen verarbeiten. Außerdem kann der Status aufgrund des Neuerstellens vonActivitydurch andere Konfigurationsänderungen, das Beenden des Prozesses oder das Schließen der App verloren gehen. Es ist unmöglich, das Neuerstellen vonActivityvollständig zu deaktivieren. Speichern Sie den Status wie unter UI-Status speichern beschrieben. - Konfigurationsänderungen nicht vermeiden:Beschränken Sie die Ausrichtung, das Seitenverhältnis oder die Größenänderung nicht, um Konfigurationsänderungen und die Neuerstellung von
Activityzu 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. Sie sind wahrscheinlicher, wenn Ihre App auf einem Gerät mit großem Display ausgeführt wird, auf dem Nutzer den Mehrfenstermodus aufrufen können. Nutzer erwarten, dass Ihre App in dieser Umgebung gut funktioniert.
Es gibt zwei allgemeine Arten von Größenänderungen: signifikante und insignifikante. Eine signifikante Größenänderung liegt vor, wenn aufgrund einer Änderung der Bildschirmgröße, z. B. der Breite, Höhe oder kleinsten Breite, ein anderer Satz alternativer Ressourcen für die neue Konfiguration gilt. Diese Ressourcen umfassen sowohl die von der App selbst definierten als auch die aus ihren Bibliotheken.
Aktivitätserstellung für größenbasierte Konfigurationsänderungen einschränken
Wenn Sie die Neuerstellung von Activity für größenbasierte Konfigurationsänderungen deaktivieren, wird das Activity nicht neu erstellt. Stattdessen wird Activity.onConfigurationChanged aufgerufen. Alle Composables, die LocalConfiguration.current lesen, werden automatisch neu zusammengesetzt, um die neue Größe zu berücksichtigen.
Die Neuerstellung von Activity ist bei größenbasierten Konfigurationsänderungen deaktiviert, wenn Sie android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout" in Ihrer Manifestdatei haben.
Zusätzliche Ressourcen
Weitere Informationen zum Umgang mit Konfigurationsänderungen finden Sie in den folgenden zusätzlichen Ressourcen: