UI-Status in „Compose“ speichern

Je nachdem, wo Ihr Bundesstaat hochgezogen wird und welche Logik erforderlich ist, kann verschiedene APIs zum Speichern und Wiederherstellen des UI-Status verwenden. Jede App verwendet ein Kombination von APIs, um dies zu erreichen.

Der Status der Benutzeroberfläche jeder Android-App kann aufgrund von Aktivitäten oder Prozessen verloren gehen. Freizeitaktivitäten. Dieser Zustandsverlust kann aufgrund der folgenden Ereignisse auftreten:

Die Bewahrung des Zustands nach diesen Ereignissen ist für positive Nutzende unerlässlich. Nutzererfahrung. Die Auswahl des dauerhaften Status hängt vom einzelnen Nutzer Ihrer App ab fließen. Als Best Practice sollten Sie zumindest die Nutzereingaben und navigiert sind. Ein Beispiel hierfür ist die Scrollposition Liste, die ID des Artikels, über den die Nutzenden mehr erfahren möchten, oder eine Eingabe in Textfeldern vornehmen.

Auf dieser Seite werden die APIs zusammengefasst, die je nachdem, wo der UI-Status gespeichert werden kann, verfügbar sind. Ihrem Zustand und der Logik, die ihn benötigt, hochgezogen wird.

UI-Logik

Wenn Ihr Zustand in der Benutzeroberfläche (entweder in zusammensetzbaren Funktionen oder im einfachen Format) hochgezogen wird. State Holding-Klassen für die Komposition an, können Sie rememberSaveable, um den Status über Aktivitäten und Neuerstellungen von Prozessen hinweg beizubehalten.

Im folgenden Snippet wird rememberSaveable verwendet, um einen einzelnen booleschen Wert zu speichern Status des UI-Elements:

@Composable
fun ChatBubble(
    message: Message
) {
    var showDetails by rememberSaveable { mutableStateOf(false) }

    ClickableText(
        text = AnnotatedString(message.content),
        onClick = { showDetails = !showDetails }
    )

    if (showDetails) {
        Text(message.timestamp)
    }
}

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
Abbildung 1. Das Infofeld für die Chatnachricht wird beim Antippen maximiert und minimiert.

showDetails ist eine boolesche Variable, die gespeichert wird, wenn das Infofeld minimiert ist oder maximiert werden.

rememberSaveable speichert den UI-Elementstatus in einem Bundle-Objekt über das Mechanismus zum Speichern gespeicherter Instanzstatus.

Primitive Typen können automatisch im Bundle gespeichert werden. Wenn Ihr Bundesland in einem Typ enthalten ist, der nicht primitiv ist, wie z. B. eine Datenklasse, können Sie verschiedene Speichermechanismen verwenden, z. B. die Annotation Parcelize, wie listSaver und mapSaver oder die Implementierung eines Die benutzerdefinierte Saver-Klasse erweitert die Saver-Klasse der Compose-Laufzeit. Möglichkeiten kennenlernen zum Speichern des Status, um mehr über diese Methoden zu erfahren.

Im folgenden Snippet führt die Funktion rememberLazyListState Compose Die API speichert LazyListState, was aus dem Scrollstatus eines LazyColumn oder LazyRow mit rememberSaveable Dabei wird ein LazyListState.Saver ist ein benutzerdefinierter Speicher, mit dem Bildlaufstatus speichern und wiederherstellen. Nach einer Aktivität oder einem Prozess z. B. nach einer Konfigurationsänderung wie dem Ändern der Geräteausrichtung), der Scroll-Status beibehalten wird.

@Composable
fun rememberLazyListState(
    initialFirstVisibleItemIndex: Int = 0,
    initialFirstVisibleItemScrollOffset: Int = 0
): LazyListState {
    return rememberSaveable(saver = LazyListState.Saver) {
        LazyListState(
            initialFirstVisibleItemIndex, initialFirstVisibleItemScrollOffset
        )
    }
}

Best Practice

rememberSaveable verwendet einen Bundle zum Speichern des UI-Status, der von andere APIs, die ebenfalls schreiben, z. B. onSaveInstanceState()-Aufrufe in Ihre Aktivitäten. Die Größe dieses Bundle ist jedoch begrenzt und es können große Datenmengen gespeichert werden, -Objekte können in der Laufzeit zu TransactionTooLarge-Ausnahmen führen. Dieses kann besonders bei einzelnen Activity-Apps problematisch sein, in denen dieselben „Bundle“ wird in der gesamten App verwendet.

Um diese Art von Absturz zu vermeiden, sollten Sie keine großen, komplexen Objekte oder Liste der Objekte im Bundle

Speichern Sie stattdessen den erforderlichen Mindeststatus wie IDs oder Schlüssel und verwenden Sie diese, um die Wiederherstellung komplexerer Benutzeroberflächenstatus an andere Mechanismen, wie z. B. persistente Speicherplatz.

Diese Designentscheidungen hängen von den spezifischen Anwendungsfällen für Ihre App und davon ab, wie Nutzende es erwarten.

Statuswiederherstellung bestätigen

Sie können prüfen, ob der mit rememberSaveable gespeicherte Status in Ihrem „Compose“-Elemente werden korrekt wiederhergestellt, wenn die Aktivität oder der Prozess neu erstellt. Dafür gibt es spezielle APIs, z. B. StateRestorationTester In der Dokumentation zum Testen erfahren Sie, Weitere Informationen

Geschäftslogik

Wenn der UI-Elementstatus auf ViewModel hochgezogen wird, weil es die für die Geschäftslogik erforderlich sind, können Sie die APIs von ViewModel verwenden.

Einer der Hauptvorteile der Verwendung von ViewModel in Ihrer Android-App ist Konfigurationsänderungen kostenlos verarbeitet. Wenn eine Konfiguration vorhanden ist, geändert und die Aktivität zerstört und neu erstellt wurde, ViewModel wird im Arbeitsspeicher gehalten. Nach der Neuerstellung wird die alte ViewModel -Instanz an die neue Activity-Instanz angehängt wird.

Eine ViewModel-Instanz überlebt jedoch nicht den vom System initiierten Prozessabschluss. Damit der UI-Status weiterhin auftritt, verwenden Sie das Modul Saved State ViewModel, in dem die SavedStateHandle API enthalten ist.

Best Practice

SavedStateHandle verwendet auch den Bundle-Mechanismus zum Speichern des UI-Status. sollten Sie ihn nur verwenden, um einfache UI-Elementstatus zu speichern.

Bildschirm-UI-Status: Dieser wird durch die Anwendung von Geschäftsregeln und den Zugriff auf sollten abgesehen von der UI nicht in den SavedStateHandle aufgrund der potenziellen Komplexität und Größe. Sie können verschiedene Mechanismen zur Speicherung komplexer oder großer Daten, wie lokale Speicherplatz. Nach der Wiederherstellung des Prozesses wird der Bildschirm mit dem wiederhergestellten temporären Status, der in SavedStateHandle (sofern vorhanden) gespeichert war, und Der Bildschirm-UI-Status wird aus der Datenschicht erneut erzeugt.

SavedStateHandle-APIs

SavedStateHandle hat verschiedene APIs zum Speichern des UI-Elementstatus. Die meisten insbesondere:

„Schreiben“ State saveable()
StateFlow getStateFlow()

State“ verfassen

Die saveable API von SavedStateHandle zum Lesen und Schreiben von UI-Elementen verwenden Zustand als MutableState, sodass sie Aktivitäten und Neuerstellungen mit mit minimalem Code einrichten.

Die saveable API unterstützt standardmäßig primitive Typen und empfängt einen stateSaver, um benutzerdefinierte Speichervorgänge wie rememberSaveable() zu verwenden.

Im folgenden Snippet speichert message die Nutzereingabetypen in einem TextField:

class ConversationViewModel(
    savedStateHandle: SavedStateHandle
) : ViewModel() {

    var message by savedStateHandle.saveable(stateSaver = TextFieldValue.Saver) {
        mutableStateOf(TextFieldValue(""))
    }
        private set

    fun update(newMessage: TextFieldValue) {
        message = newMessage
    }

    /*...*/
}

val viewModel = ConversationViewModel(SavedStateHandle())

@Composable
fun UserInput(/*...*/) {
    TextField(
        value = viewModel.message,
        onValueChange = { viewModel.update(it) }
    )
}

Weitere Informationen finden Sie in der Dokumentation zu SavedStateHandle. mit der saveable API.

StateFlow

Verwenden Sie getStateFlow(), um den Status der UI-Elemente zu speichern und als Ablauf zu verarbeiten. aus dem SavedStateHandle. StateFlow wird gelesen und die API erfordert, dass Sie einen Schlüssel angeben, damit Sie den Ablauf zu gibt einen neuen Wert aus. Mit dem von Ihnen konfigurierten Schlüssel können Sie den StateFlow abrufen und den neuesten Wert erfassen.

Im folgenden Snippet ist savedFilterType eine StateFlow-Variable, die speichert einen Filtertyp, der auf eine Liste von Chatkanälen in einer Chat-App angewendet wird:

private const val CHANNEL_FILTER_SAVED_STATE_KEY = "ChannelFilterKey"

class ChannelViewModel(
    channelsRepository: ChannelsRepository,
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    private val savedFilterType: StateFlow<ChannelsFilterType> = savedStateHandle.getStateFlow(
        key = CHANNEL_FILTER_SAVED_STATE_KEY, initialValue = ChannelsFilterType.ALL_CHANNELS
    )

    private val filteredChannels: Flow<List<Channel>> =
        combine(channelsRepository.getAll(), savedFilterType) { channels, type ->
            filter(channels, type)
        }.onStart { emit(emptyList()) }

    fun setFiltering(requestType: ChannelsFilterType) {
        savedStateHandle[CHANNEL_FILTER_SAVED_STATE_KEY] = requestType
    }

    /*...*/
}

enum class ChannelsFilterType {
    ALL_CHANNELS, RECENT_CHANNELS, ARCHIVED_CHANNELS
}

Jedes Mal, wenn der Nutzer einen neuen Filtertyp auswählt, wird setFiltering aufgerufen. Dieses speichert einen neuen Wert in SavedStateHandle, der mit dem Schlüssel gespeichert wird _CHANNEL_FILTER_SAVED_STATE_KEY_. savedFilterType ist ein Fluss, der den zuletzt im Schlüssel gespeicherter Wert. filteredChannels hat den Ablauf abonniert für den Kanal zu filtern.

In der Dokumentation zu SavedStateHandle finden Sie weitere Informationen zu den getStateFlow() API verwenden.

Zusammenfassung

In der folgenden Tabelle sind die in diesem Abschnitt behandelten APIs und ihre Verwendungsmöglichkeiten zusammengefasst. um den Status der Benutzeroberfläche zu speichern:

Veranstaltung UI-Logik Geschäftslogik in einem ViewModel
Konfigurationsänderungen rememberSaveable Automatisch
Vom System initiierter Prozess beendet rememberSaveable SavedStateHandle

Welche API zu verwenden ist, hängt davon ab, wo sich der Status befindet und welche Logik er verwendet. . Für den Status, der in der UI-Logik verwendet wird, verwenden Sie rememberSaveable. Für der in der Geschäftslogik verwendet wird, wenn Sie ihn in einem ViewModel, mit SavedStateHandle speichern.

Sie sollten die Bundle-APIs (rememberSaveable und SavedStateHandle) verwenden, um kleine UI-Zustände speichern. Diese Daten sind das Minimum, das für die Wiederherstellung der UI wieder auf den vorherigen Zustand zurück, zusammen mit anderen Speichermechanismen. Für Wenn Sie beispielsweise die ID eines Profils speichern, das sich der Nutzer im Bundle angesehen hat, können Sie umfangreiche Daten wie Profildetails aus der Datenschicht abrufen.

Weitere Informationen zu den verschiedenen Möglichkeiten zum Speichern des UI-Status finden Sie in der allgemeinen Speichern der UI State-Dokumentation und der Datenschichtseite des Architekturleitfaden.