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를 사용하여 화면 및 경로 유형을 비공개로 유지하기