탐색 상태 저장 및 관리

다음 섹션에서는 백 스택을 저장하고 백 스택의 항목과 연결된 상태를 저장하는 전략을 설명합니다.

백 스택 저장

우수한 사용자 환경을 제공하려면 구성 변경 및 프로세스 종료와 같은 다양한 수명 주기 이벤트에서 앱의 탐색 상태가 유지되도록 하는 것이 중요합니다. Navigation 3에서는 백 스택을 소유하므로 백 스택을 생성하거나 저장하는 방법에 관한 엄격한 가이드라인이 없습니다. 그러나 Navigation 3에서는 저장 가능한 백 스택을 제공하는 편의 메서드인 rememberNavBackStack를 제공합니다.

rememberNavBackStack 사용

rememberNavBackStack 컴포저블 함수는 구성 변경 및 프로세스 종료 전후에 유지되는 백 스택을 만들도록 설계되었습니다.

rememberNavBackStack가 올바르게 작동하려면 백 스택의 각 키가 다음과 같은 특정 요구사항을 준수해야 합니다.

  • NavKey 인터페이스 구현: 백 스택의 모든 키는 NavKey 인터페이스를 구현해야 합니다. 이는 키를 저장할 수 있음을 라이브러리에 알리는 마커 인터페이스 역할을 합니다.
  • @Serializable 주석이 있음: NavKey를 구현하는 것 외에도 키 클래스와 객체는 @Serializable 주석으로 표시해야 합니다.

다음 스니펫은 rememberNavBackStack의 올바른 구현을 보여줍니다.

@Serializable
data object Home : NavKey

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

대안: ViewModel에 저장

백 스택을 관리하는 또 다른 방법은 ViewModel에 저장하는 것입니다. ViewModel 또는 기타 맞춤 저장소를 사용할 때 프로세스 종료를 통한 지속성을 보장하려면 다음을 실행해야 합니다.

  • 키가 직렬화 가능해야 함: rememberNavBackStack와 마찬가지로 탐색 키는 직렬화 가능해야 합니다.
  • 직렬화 및 역직렬화를 수동으로 처리: 각 키의 직렬화된 표현을 영구 저장소 (예: SharedPreferences, 데이터베이스 또는 파일)을 저장합니다.

ViewModelNavEntry로 범위 지정

ViewModels는 화면 회전과 같은 구성 변경 전반에서 UI 관련 상태를 유지하는 데 사용됩니다. 기본적으로 ViewModels의 범위는 가장 가까운 ViewModelStoreOwner(일반적으로 Activity 또는 Fragment)로 설정됩니다.

하지만 ViewModel의 범위를 전체 Activity가 아닌 백 스택의 특정 NavEntry (예: 특정 화면 또는 대상)로 지정하는 것이 좋습니다. 이렇게 하면 특정 NavEntry가 백 스택에 있는 동안만 ViewModel의 상태가 유지되고 NavEntry가 팝되면 삭제됩니다.

androidx.lifecycle:lifecycle-viewmodel-navigation3 부가기능 라이브러리는 이를 용이하게 하는 NavEntryDecorator를 제공합니다. 이 데코레이터는 각 NavEntryViewModelStoreOwner를 제공합니다. NavEntry의 콘텐츠 내에 ViewModel를 만들면 (예: Compose에서 viewModel() 사용) 백 스택의 해당 NavEntry 키로 자동으로 범위가 지정됩니다. 즉, NavEntry가 백 스택에 추가될 때 ViewModel이 생성되고 삭제될 때 삭제됩니다.

ViewModelNavEntry로 범위 지정하는 데 NavEntryDecorator를 사용하려면 다음 단계를 따르세요.

  1. androidx.lifecycle:lifecycle-viewmodel-navigation3 종속 항목을 app/build.gradle.kts 파일에 추가합니다.
  2. NavDisplay를 구성할 때 entryDecorators 목록에 rememberSavedStateNavEntryDecorator()를 추가합니다.
  3. NavDisplay에 다른 데코레이터를 추가합니다.

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