프래그먼트 및 Kotlin DSL

탐색 구성요소가 Kotlin 기반의 도메인별 언어를 제공합니다. Kotlin의 유형 안전 빌더 에서 자세한 내용을 확인하실 수 있습니다. 이 API를 사용하면 Kotlin 코드에서 그래프를 선언적으로 구성할 수 있습니다. 더 많이 가져야 합니다. 이는 앱의 대규모 언어 모델을 빌드하고자 할 때 있습니다. 예를 들어 앱이 탐색 구성을 가져와서 탐색 그래프를 동적으로 빌드하는 구성 onCreate() 함수를 사용하세요.

종속 항목

프래그먼트와 함께 Kotlin DSL을 사용하려면 앱의 build.gradle 파일:

Groovy

dependencies {
    def nav_version = "2.8.0"

    api "androidx.navigation:navigation-fragment-ktx:$nav_version"
}

Kotlin

dependencies {
    val nav_version = "2.8.0"

    api("androidx.navigation:navigation-fragment-ktx:$nav_version")
}

그래프 빌드

이 예에서는 Sunflower 앱을 엽니다. 이 작업 예를 들어 homeplant_detail의 두 대상이 있습니다. 사용자가 처음으로 앱을 실행하면 home 대상이 표시됩니다. 이 대상은 사용자의 정원에 있는 식물 목록을 표시합니다. 사용자가 식물 중 하나를 선택하면 앱이 plant_detail 대상으로 이동합니다.

그림 1은 plant_detail 대상에서 요구하는 인수와 앱이 home에서 plant_detail로 이동할 때 사용하는 작업인 to_plant_detail을 함께 보여줍니다.

Sunflower 앱에는 두 개의 대상과 두 대상을 연결하는 작업이 있습니다.
그림 1. Sunflower 앱에는 homeplant_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)

경로를 정의한 후에는 탐색 그래프를 빌드할 수 있습니다.

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 빌더 함수입니다. 이 함수에는 두 가지 유형이 필요합니다. 인수 에서 자세한 내용을 확인하실 수 있습니다.

먼저 Fragment 클래스 UI를 제공합니다. 이를 설정하면 정의된 프래그먼트 대상에서 android:name 속성 설정 할 수 있습니다.

둘째, 경로 이는 Any에서 확장되는 직렬화 가능한 유형이어야 합니다. 그것은 이 대상에서 사용할 탐색 인수를 포함해야 합니다. 지정할 수 있습니다

이 함수는 추가 구성을 위해 선택적 람다도 허용합니다. 예를 들면 다음과 같습니다. 대상 라벨 및 커스텀용 삽입된 빌더 함수 인수 및 딥 링크를 사용할 수 있습니다.

마지막으로 다음을 사용하여 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

PlantDetailFragmentViewModel를 사용 중인 경우 다음을 사용하여 경로 인스턴스를 가져옵니다. 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() 드림 DSL 함수를 사용하여 중첩된 탐색을 빌드할 수 있음 그래프를 참고하세요. 이 함수는 이 그래프에 할당할 경로의 매개변수입니다. 또한 다음과 같은 두 개의 인수를 사용합니다. 그래프의 시작 대상 경로 및 추가 람다를 통해 그래프를 구성할 수 있습니다 유효한 요소에는 다른 대상, 커스텀 인수가 포함됨 유형, 딥 링크, 구체적인 라벨을 지정합니다. 대상입니다. 이 라벨은 다음을 사용하여 탐색 그래프를 UI 구성요소에 결합하는 데 유용할 수 있습니다. NavigationUI

@Serializable data object HomeGraph
@Serializable data object Home

navigation<HomeGraph>(startDestination = Home) {
   // label, other destinations, deep links
}

맞춤 대상 지원

새로운 대상 유형을 사용하는 경우 Kotlin DSL을 직접 지원하지 않는 경우 이러한 대상을 Kotlin DSL을 addDestination():

// 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
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> {
    label = getString(R.string.plant_search_title)
    typeMap = mapOf(typeOf<SearchParameters>() to SearchParametersType)
}

대상으로 이동할 때 경로의 인스턴스를 만듭니다.

val params = SearchParameters("rose", listOf("available"))
navController.navigate(route = SearchRoute(params))

매개변수는 대상의 경로에서 가져올 수 있습니다.

val searchRoute = navController().getBackStackEntry<SearchRoute>().toRoute<SearchRoute>()
val params = searchRoute.parameters

딥 링크

딥 링크는 XML 기반 탐색 그래프와 함께 추가될 수 있는 것처럼 모든 대상에 추가 가능합니다. 딥 링크 만들기에 정의된 것과 동일한 절차 대상이 프로세스에 가이드를 마치겠습니다

암시적 딥 링크를 만드는 경우 그러나 <deepLink> 요소 따라서 <nav-graph> 요소를 AndroidManifest.xml 파일에 추가하고 인텐트를 추가해야 함 필터를 활동에 수동으로 적용할 수 있습니다. 인텐트 기본 경로, 작업 및 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과 호환되지 않습니다. 플러그인이 DirectionsArguments 클래스를 생성하기 위해 XML 리소스 파일을 찾기 때문입니다.