Kotlin DSL을 사용하여 그래프를 구성할 때 대상과 탐색 이벤트는 유지관리가 어려울 수 있습니다. 이것은 특히 여러 개의 독립적인 특성이 있는 경우에 더 그렇습니다.
대상 추출
대상을 NavGraphBuilder
확장 프로그램으로 이동해야 합니다.
함수와 비교합니다. 이들은 자신을 정의하는 경로 근처에 거주해야 하며
표시할 수 있습니다. 예를 들어 다음과 같은 앱 수준 코드를
연락처 목록을 표시하는 대상을 만듭니다.
// MyApp.kt
@Serializable
object Contacts
@Composable
fun MyApp() {
...
NavHost(navController, startDestination = Contacts) {
composable<Contacts> { ContactsScreen( /* ... */ ) }
}
}
탐색 관련 코드를 별도의 파일로 이동해야 합니다.
// ContactsNavigation.kt
@Serializable
object Contacts
fun NavGraphBuilder.contactsDestination() {
composable<Contacts> { ContactsScreen( /* ... */ ) }
}
// MyApp.kt
@Composable
fun MyApp() {
...
NavHost(navController, startDestination = Contacts) {
contactsDestination()
}
}
이제 경로 및 대상 정의가 기본 앱과 별개이며
독립적으로 업데이트할 수 있습니다 기본 앱은 단일 앱에만 의존합니다.
확장 함수와 함께 사용합니다. 이 경우
NavGraphBuilder.contactsDestination()
NavGraphBuilder
확장 함수는 스테이트리스(Stateless) 및
화면 수준의 구성 가능한 함수와 탐색 관련 로직입니다. 이 레이어는
상태의 출처와 이벤트 처리 방법도 정의합니다.
예
다음 스니펫은 연락처의 기존 연락처 목록 대상을 업데이트하여 탐색 이벤트를 사용하여 연락처 세부정보를 표시합니다.
다음은 자체 모듈에 대해 internal
할 수 있는 일반적인 화면 세트입니다.
다른 모듈에서 액세스할 수 없습니다.
// ContactScreens.kt
// Displays a list of contacts
@Composable
internal fun ContactsScreen(
uiState: ContactsUiState,
onNavigateToContactDetails: (contactId: String) -> Unit
) { ... }
// Displays the details for an individual contact
@Composable
internal fun ContactDetailsScreen(contact: ContactDetails) { ... }
대상 만들기
다음 NavGraphBuilder
확장 함수는 대상을 만듭니다.
이 코드는 ContactsScreen
컴포저블을 보여줍니다. 또한 이제
화면 UI 상태를 제공하고ViewModel
화면 관련 비즈니스 로직을
작성할 수 있습니다
연락처 세부정보 목적지로 이동과 같은 탐색 이벤트는
ViewModel
에 의해 처리되지 않고 호출자에 노출됩니다.
// ContactsNavigation.kt
@Serializable
object Contacts
// Adds contacts destination to `this` NavGraphBuilder
fun NavGraphBuilder.contactsDestination(
// Navigation events are exposed to the caller to be handled at a higher level
onNavigateToContactDetails: (contactId: String) -> Unit
) {
composable<Contacts> {
// The ViewModel as a screen level state holder produces the screen
// UI state and handles business logic for the ConversationScreen
val viewModel: ContactsViewModel = hiltViewModel()
val uiState = viewModel.uiState.collectAsStateWithLifecycle()
ContactsScreen(
uiState,
onNavigateToContactDetails
)
}
}
동일한 접근 방식을 사용하여
ContactDetailsScreen
이 경우 UI 상태를 가져오는 대신
NavBackStackEntry
에서 직접 가져올 수 있습니다.
// ContactsNavigation.kt
@Serializable
internal data class ContactDetails(val id: String)
fun NavGraphBuilder.contactDetailsScreen() {
composable<ContactDetails> { navBackStackEntry ->
ContactDetailsScreen(contact = navBackStackEntry.toRoute())
}
}
탐색 이벤트 캡슐화
대상을 캡슐화하는 것과 같은 방식으로
탐색 이벤트를 사용하여 경로 유형을 불필요하게 노출하지 않도록 합니다. 수행 기준
NavController
에서 확장 함수 만들기
// ContactsNavigation.kt
fun NavController.navigateToContactDetails(id: String) {
navigate(route = ContactDetails(id = id))
}
총정리
이제 연락처를 표시하기 위한 탐색 코드가 앱의 탐색 그래프에 포함되어 있습니다. 앱은 다음 요건을 충족해야 합니다.
NavGraphBuilder
확장 함수를 호출하여 대상을 만듭니다.NavController
확장 함수를 호출하여 이러한 대상을 연결합니다. 탐색 이벤트
// MyApp.kt
@Composable
fun MyApp() {
...
NavHost(navController, startDestination = Contacts) {
contactsDestination(onNavigateToContactDetails = { contactId ->
navController.navigateToContactDetails(id = contactId)
})
contactDetailsDestination()
}
}
요약
- 관련 화면 세트의 탐색 코드를 배치하여 캡슐화합니다. 별도의 파일에 포함
NavGraphBuilder
에서 확장 함수를 만들어 대상을 노출합니다.NavController
에서 확장 함수를 만들어 탐색 이벤트를 노출합니다.internal
를 사용하여 화면 및 경로 유형을 비공개로 유지하기