탐색 상태 저장 및 관리

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

백 스택 저장

구성 변경 및 프로세스 종료를 비롯한 다양한 수명 주기 이벤트에서 앱의 탐색 상태가 유지되도록 하는 것은 우수한 사용자 환경을 위해 매우 중요합니다. 탐색 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, 데이터베이스 또는 파일)을 저장해야 합니다.

ViewModel초~NavEntry초 범위 지정

ViewModels은 화면 회전과 같은 구성 변경 시 UI 관련 상태를 유지하는 데 사용됩니다. 기본적으로 ViewModels는 가장 가까운 ViewModelStoreOwner로 범위가 지정되며, 이는 일반적으로 Activity 또는 Fragment입니다.

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

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

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

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

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 { },
)