탐색 구성요소는 Kotlin 기반의 도메인별 언어인 DSL을 제공하며, DSL은 Kotlin의 유형 안전 빌더를 사용합니다. 이 API를 사용하면 Kotlin 코드에서 그래프를 선언적으로 구성할 수 있습니다.
더 많이 가져야 합니다. 앱의 탐색을 동적으로 빌드하고자 할 때 유용합니다. 예를 들어 앱에서 외부 웹 서비스의 탐색 구성을 다운로드 및 캐시한 다음, 이 구성을 사용해 활동의 onCreate()
함수에서 탐색 그래프를 동적으로 빌드할 수 있습니다.
종속 항목
프래그먼트와 함께 Kotlin DSL을 사용하려면 앱의
build.gradle
파일:
Groovy
dependencies { def nav_version = "2.9.2" api "androidx.navigation:navigation-fragment-ktx:$nav_version" }
Kotlin
dependencies { val nav_version = "2.9.2" api("androidx.navigation:navigation-fragment-ktx:$nav_version") }
그래프 빌드
다음은 Sunflower 앱을 기반으로 한 기본 예시입니다. 이 예시에는 home
및 plant_detail
이라는 두 개의 대상이 있습니다. 사용자가 처음으로 앱을 실행하면 home
대상이 표시됩니다. 이 대상은 사용자의 정원에 있는 식물 목록을 표시합니다. 사용자가 식물 중 하나를 선택하면 앱이 plant_detail
대상으로 이동합니다.
그림 1은 plant_detail
대상에서 요구하는 인수와 앱이 home
에서 plant_detail
로 이동할 때 사용하는 작업인 to_plant_detail
을 함께 보여줍니다.

home
및 plant_detail
이라는 두 개의 대상과 두 대상을 연결하는 작업이 있습니다.Kotlin DSL 탐색 그래프 호스팅
앱의 탐색 그래프를 빌드하려면 그래프를 호스팅할 위치가 필요합니다. 이 예에서는 앱이 FragmentContainerView
내부에 있는 NavHostFragment
에 그래프를 호스팅하도록 프래그먼트를 사용합니다.
<!-- activity_garden.xml -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true" />
</FrameLayout>
참고로, 이 예에서는 app:navGraph
속성이 설정되어 있지 않습니다. 그래프
리소스로 정의되지 않은
res/navigation
폴더에 저장되므로 onCreate()
의 일부로 설정해야 합니다.
모든 프로세스와 관련이 있습니다.
XML에서 작업은 하나 이상의 인수가 있는 대상 ID를 서로 연결합니다. 그러나 Navigation DSL을 사용할 때 경로는 경로 즉, DSL을 사용할 때는 작업에 대한 개념이 없습니다.
다음 단계는 그래프를 정의할 때 사용할 경로를 정의하는 것입니다.
그래프 경로 만들기
XML 기반 탐색 그래프는 부분적으로 파싱됩니다.
몇 가지 단계를 살펴봤습니다 id
마다 숫자 상수가 생성됩니다.
속성입니다. 이러한 빌드 시간 생성 정적 ID는
런타임 시 탐색 그래프를 빌드할 때 사용할 수 있으므로 Navigation DSL은
직렬화 가능한 파일을
유형이 아닌
있습니다. 각 경로는 고유한 유형으로 표시됩니다.
인수를 처리할 때 인수는 경로 유형에 포함됩니다. 이렇게 하면 탐색 인수에 유형 안전성을 적용할 수 있습니다.
@Serializable data object Home
@Serializable data class Plant(val id: String)
NavGraphBuilder DSL로 그래프 빌드
경로를 정의한 후에는 탐색 그래프를 빌드할 수 있습니다.
val navController = findNavController(R.id.nav_host_fragment)
navController.graph = navController.createGraph(
startDestination = Home
) {
fragment<HomeFragment, Home> {
label = resources.getString(R.string.home_title)
}
fragment<PlantDetailFragment, PlantDetail> {
label = resources.getString(R.string.plant_detail_title)
}
}
이 예에서는 두 개의 프래그먼트 대상을
fragment()
DSL 빌더 함수입니다. 이 함수에는 두 가지 유형이 필요합니다.
인수
에서 자세한 내용을 확인하실 수 있습니다.
첫 번째는 이 대상의 UI를 제공하는 Fragment
클래스입니다. 이를 설정하면 XML을 사용하여 정의된 프래그먼트 대상에 android:name
속성을 설정하는 것과 동일한 효과가 있습니다.
둘째, 경로 Any
에서 확장되는 직렬화 가능한 유형이어야 합니다. 이 대상에서 사용할 탐색 인수와 유형을 포함해야 합니다.
이 함수는 추가 구성을 위해 선택적 람다도 허용합니다. 예를 들면 다음과 같습니다. 대상 라벨 및 커스텀용 삽입된 빌더 함수 인수 및 딥 링크를 사용할 수 있습니다.
Kotlin DSL 그래프로 탐색
마지막으로 다음을 사용하여 home
에서 plant_detail
로 이동할 수 있습니다.
NavController.navigate()
통화:
private fun navigateToPlant(plantId: String) {
findNavController().navigate(route = PlantDetail(id = plantId))
}
PlantDetailFragment
에서는
현재
NavBackStackEntry
및 통화
toRoute
경로 인스턴스를 가져옵니다.
val plantDetailRoute = findNavController().getBackStackEntry<PlantDetail>().toRoute<PlantDetail>()
val plantId = plantDetailRoute.id
PlantDetailFragment
가 ViewModel
를 사용하는 경우 SavedStateHandle.toRoute
를 사용하여 경로 인스턴스를 가져옵니다.
val plantDetailRoute = savedStateHandle.toRoute<PlantDetail>()
val plantId = plantDetailRoute.id
이 가이드의 나머지 부분에서는 일반적인 탐색 그래프 요소, 대상, 및 그래프 빌드 시 이러한 요소를 사용하는 방법을 설명합니다.
대상
Kotlin DSL은 세 가지 대상 유형을 기본적으로 지원하며, Fragment
대상, Activity
대상, NavGraph
대상이 이에 해당합니다. 각 항목에는 해당 대상을 빌드하고 구성하는 데 사용할 수 있는 자체 인라인 확장 함수가 있습니다.
Fragment 대상
fragment()
DSL 함수는 UI의 프래그먼트 클래스와 이 대상을 고유하게 식별하는 데 사용되는 경로 유형으로 매개변수화될 수 있으며, 이 다음에는 Kotlin DSL 그래프로 탐색 섹션에 설명된 대로 추가 구성을 제공할 수 있는 람다가 옴.
fragment<MyFragment, MyRoute> {
label = getString(R.string.fragment_title)
// custom argument types, deepLinks
}
Activity 대상
이
activity()
DSL 함수가 경로의 유형 매개변수를 취하지만
구현 활동 클래스 대신 activityClass
후행 람다입니다. 이러한 유연성을 통해 활동 대상을 정의할 수 있어
암시적
인텐트로, 여기서 명시적
말이 되지 않을 것입니다. 프래그먼트 대상과 마찬가지로
라벨, 커스텀 인수, 딥 링크를 구성할 수 있습니다.
activity<MyRoute> {
label = getString(R.string.activity_title)
// custom argument types, deepLinks...
activityClass = MyActivity::class
}
Navigation graph 대상
navigation()
DSL 함수를 사용하여 중첩된 탐색 그래프를 빌드할 수 있습니다. 이 함수는
이 그래프에 할당할 경로의 매개변수입니다. 또한 그래프의 시작 대상 경로와 그래프를 추가로 구성할 람다라는 두 가지 인수를 취합니다. 유효한 요소에는 다른 대상, 커스텀 인수가 포함됨
유형, 딥 링크, 구체적인 라벨을 지정합니다.
대상입니다.
이 라벨은 NavigationUI
를 사용하여 탐색 그래프를 UI 구성요소에 결합하는 데 유용할 수 있습니다.
@Serializable data object HomeGraph
@Serializable data object Home
navigation<HomeGraph>(startDestination = Home) {
// label, other destinations, deep links
}
맞춤 대상 지원
사용 중인 새 대상 유형이 Kotlin DSL을 직접 지원하지 않는 경우 다음과 같이 addDestination()
을 사용하여 이러한 대상을 Kotlin DSL에 추가할 수 있습니다.
// The NavigatorProvider is retrieved from the NavController
val customDestination = navigatorProvider[CustomNavigator::class].createDestination().apply {
route = Graph.CustomDestination.route
}
addDestination(customDestination)
또는 단항 플러스 연산자를 사용하여 새로 구성된 대상을 그래프에 직접 추가할 수도 있습니다.
// The NavigatorProvider is retrieved from the NavController
+navigatorProvider[CustomNavigator::class].createDestination().apply {
route = Graph.CustomDestination.route
}
대상 인수 제공
대상 인수는 경로 클래스의 일부로 정의할 수 있습니다. 이는 모든 Kotlin 클래스와 동일한 방식으로 정의할 수 있습니다. 필수 인수는 다음과 같습니다. null을 허용하지 않는 유형으로 정의되고 선택적 인수는 기본값으로 정의됨 값으로 사용됩니다.
경로 및 그 인수를 나타내는 기본 메커니즘은 문자열입니다.
기반으로 합니다. 문자열을 사용하여 경로를 모델링하면 탐색 상태를 저장하고
구성 중 디스크에서 복원됨
변경사항 및 시스템에서 시작된 프로세스
사망에 이르렀습니다. 따라서
각 탐색 인수는 직렬화 가능해야 합니다. 즉,
이 메서드는 인수 값의 메모리 내 표현을
String
Kotlin 직렬화는
플러그인
직렬화 메서드 기본 생성
유형이
@Serializable
주석이 객체에 추가됩니다.
@Serializable
data class MyRoute(
val id: String,
val myList: List<Int>,
val optionalArg: String? = null
)
fragment<MyFragment, MyRoute>
맞춤 유형 제공
맞춤 인수 유형의 경우 맞춤 NavType
클래스를 제공해야 합니다. 이렇게 하면 경로 또는 딥 링크에서 유형을 파싱하는 방식을 정확하게 제어할 수 있습니다.
예를 들어 검색 화면을 정의하는 데 사용되는 경로에는 검색 매개변수를 나타냅니다.
@Serializable
data class SearchRoute(val parameters: SearchParameters)
@Serializable
@Parcelize
data class SearchParameters(
val searchQuery: String,
val filters: List<String>
)
맞춤 NavType
을 다음과 같이 작성할 수 있습니다.
val SearchParametersType = object : NavType<SearchParameters>(
isNullableAllowed = false
) {
override fun put(bundle: Bundle, key: String, value: SearchParameters) {
bundle.putParcelable(key, value)
}
override fun get(bundle: Bundle, key: String): SearchParameters {
return bundle.getParcelable(key) as SearchParameters
}
override fun serializeAsValue(value: SearchParameters): String {
// Serialized values must always be Uri encoded
return Uri.encode(Json.encodeToString(value))
}
override fun parseValue(value: String): SearchParameters {
// Navigation takes care of decoding the string
// before passing it to parseValue()
return Json.decodeFromString<SearchParameters>(value)
}
}
그런 다음 이를 다른 유형과 마찬가지로 Kotlin DSL에서 사용할 수 있습니다.
fragment<SearchFragment, SearchRoute>(
typeMap = mapOf(typeOf<SearchParameters>() to SearchParametersType)
) {
label = getString(R.string.plant_search_title)
}
목적지로 이동할 때 경로의 인스턴스를 만듭니다.
val params = SearchParameters("rose", listOf("available"))
navController.navigate(route = SearchRoute(params))
매개변수는 대상의 경로에서 가져올 수 있습니다.
val searchRoute = navController().getBackStackEntry<SearchRoute>().toRoute<SearchRoute>()
val params = searchRoute.parameters
딥 링크
딥 링크는 XML 기반 탐색 그래프와 함께 추가될 수 있는 것처럼 모든 대상에 추가 가능합니다. 대상의 딥 링크 만들기에서 정의된 것과 동일한 모든 절차가 Kotlin DSL을 사용하는 딥 링크 만들기 프로세스에도 적용됩니다.
하지만 암시적 딥 링크를 만들 때는 <deepLink>
요소를 분석할 수 있는 XML 탐색 리소스가 없습니다. 따라서 AndroidManifest.xml
파일에 <nav-graph>
요소를 배치할 수 없으므로 활동에 수동으로 인텐트 필터를 추가해야 합니다. 인텐트
기본 경로, 작업 및 MIME 유형과 일치해야 합니다.
딥 링크를 설정할 수 있습니다.
내부에서 deepLink
함수를 호출하여 대상에 딥 링크를 추가합니다.
대상의 람다입니다. 경로를 매개변수화된 유형으로 허용하고 딥 링크에 사용되는 URL의 기본 경로에 관한 매개변수 basePath
를 허용합니다.
또한
deepLinkBuilder
후행 람다입니다.
다음 예시에서는 Home
대상의 딥 링크 URI를 만듭니다.
@Serializable data object Home
fragment<HomeFragment, Home>{
deepLink<Home>(basePath = "www.example.com/home"){
// Optionally, specify the action and/or mime type that this destination
// supports
action = "android.intent.action.MY_ACTION"
mimeType = "image/*"
}
}
URI 형식
딥 링크 URI 형식은 다음 규칙을 사용하여 경로 필드에서 자동으로 생성됩니다.
- 필수 매개변수는 경로 매개변수로 추가됩니다 (예:
/{id}
). - 기본값이 있는 매개변수 (선택적 매개변수)는 query
매개변수 (예:
?name={name}
) - 컬렉션은 쿼리 매개변수로 추가됩니다(예:
?items={value1}&items={value2}
). - 매개변수의 순서는 경로의 필드 순서와 일치합니다.
예를 들어 다음과 같은 경로 유형이 있습니다.
@Serializable data class PlantDetail(
val id: String,
val name: String,
val colors: List<String>,
val latinName: String? = null,
)
생성된 URI 형식은 다음과 같습니다.
basePath/{id}/{name}/?colors={color1}&colors={color2}&latinName={latinName}
추가할 수 있는 딥 링크 수에는 제한이 없습니다. deepLink()
를 호출할 때마다 해당 대상에 대해 유지되는 목록에 새로운 딥 링크가 추가됩니다.
제한사항
Safe Args 플러그인은 Kotlin DSL과 호환되지 않습니다. 플러그인이 Directions
및 Arguments
클래스를 생성하기 위해 XML 리소스 파일을 찾기 때문입니다.