Zapisywanie stanu nawigacji i zarządzanie nim

W kolejnych sekcjach opisujemy strategie zapisywania listy wstecznej i przechowywania stanu powiązanego z elementami na tej liście.

Zapisywanie listy poprzednich ekranów

Zapewnienie, że stan nawigacji aplikacji jest zachowywany w różnych zdarzeniach cyklu życia, w tym w przypadku zmian konfiguracji i zakończenia procesu, ma kluczowe znaczenie dla wygody użytkowników. W Navigation 3 masz pełną kontrolę nad stosem wstecznym, więc nie ma ścisłych wytycznych dotyczących jego tworzenia ani zapisywania. Nawigacja 3 udostępnia jednak wygodną metodę, która zapewnia możliwość zapisania stosu wstecznego: rememberNavBackStack.

Używaj klawisza rememberNavBackStack

Funkcja z możliwością komponowania rememberNavBackStack służy do tworzenia stosu wstecznego, który zachowuje trwałość w przypadku zmian konfiguracji i zakończenia procesu.

Aby funkcja rememberNavBackStack działała prawidłowo, każdy klucz w stosie wstecznym musi spełniać określone wymagania:

  • Zaimplementuj interfejs NavKey: każdy klucz w stosie wstecznym musi implementować interfejs NavKey. Jest to interfejs znacznika, który sygnalizuje bibliotece, że klucz można zapisać.
  • Mieć adnotację @Serializable: oprócz wdrożenia NavKey klasy i obiekty kluczowe muszą być oznaczone adnotacją @Serializable.

Poniższy fragment kodu pokazuje prawidłową implementację elementu rememberNavBackStack:

@Serializable
data object Home : NavKey

@Composable
fun NavBackStack() {
    val backStack = rememberNavBackStack(Home)
}

Alternatywa: przechowywanie w ViewModel

Innym sposobem zarządzania stosem wstecznym jest przechowywanie go w ViewModel. Aby zapewnić trwałość danych po zakończeniu procesu podczas korzystania z usługi ViewModel lub dowolnej innej niestandardowej usługi pamięci masowej, musisz:

  • Upewnij się, że klucze można serializować: podobnie jak w przypadku rememberNavBackStack, klucze nawigacyjne muszą być serializowalne.
  • Ręczne obsługiwanie serializacji i deserializacji: odpowiadasz za ręczne zapisywanie w pamięci trwałej (np. SharedPreferences, bazy danych lub pliku), gdy aplikacja przechodzi w tło lub jest przywracana.

Zakres od ViewModel s do NavEntry s

ViewModels służą do zachowywania stanu interfejsu w przypadku zmian konfiguracji, takich jak obracanie ekranu. Domyślnie ViewModels są ograniczone do najbliższego ViewModelStoreOwner, którym jest zwykle Activity lub Fragment.

Możesz jednak ograniczyć zakres ViewModel do konkretnego NavEntry (czyli konkretnego ekranu lub miejsca docelowego) na liście wstecznej, a nie do całego Activity. Dzięki temu stan elementu ViewModel jest zachowywany tylko wtedy, gdy ten konkretny element NavEntry jest częścią stosu wstecznego, i jest usuwany, gdy element NavEntry jest usuwany ze stosu.

Biblioteka dodatku androidx.lifecycle:lifecycle-viewmodel-navigation3 udostępnia NavEntryDecorator, który to ułatwia. Ten dekorator udostępnia ViewModelStoreOwner dla każdego NavEntry. Gdy utworzysz ViewModel w treści NavEntry (np. za pomocą viewModel() w funkcji Compose), zostanie on automatycznie ograniczony do klucza tego konkretnego NavEntry na stosie wstecznym. Oznacza to, że element ViewModel jest tworzony, gdy element NavEntry jest dodawany do stosu wstecznego, i usuwany, gdy jest z niego usuwany.

Aby używać NavEntryDecorator do określania zakresu ViewModelNavEntry, wykonaj te czynności:

  1. Dodaj zależność androidx.lifecycle:lifecycle-viewmodel-navigation3 do pliku app/build.gradle.kts.
  2. Dodaj rememberSaveableStateHolderNavEntryDecorator() do listy entryDecorators podczas tworzenia NavDisplay.
  3. Dodaj do NavDisplay inne dekoratory.

NavDisplay(
    entryDecorators = listOf(
        // Add the default decorators for managing scenes and saving state
        rememberSaveableStateHolderNavEntryDecorator(),
        // Then add the view model store decorator
        rememberViewModelStoreNavEntryDecorator()
    ),
    backStack = backStack,
    entryProvider = entryProvider { },
)