फ़्रैगमेंट और Kotlin DSL

नेविगेशन कॉम्पोनेंट, Kotlin पर आधारित डोमेन के लिए खास भाषा उपलब्ध कराता है या DSL, जो Kotlin के टाइप-सेफ़ बिल्डर को अपनाएं. इस एपीआई की मदद से, आप अपने Kotlin कोड में, साफ़ तौर पर ग्राफ़ तैयार कर सकते हैं. ऐसा करने के बजाय, की तुलना करने के लिए किया जा सकता है. यह तब उपयोगी हो सकता है, जब आप अपने ऐप्लिकेशन का नेविगेशन की सुविधा देता है. उदाहरण के लिए, आपका ऐप्लिकेशन नेविगेशन कॉन्फ़िगरेशन को कॉन्फ़िगर किया है और फिर उसका इस्तेमाल किया है आपकी गतिविधि के डेटा में, डाइनैमिक रूप से नेविगेशन ग्राफ़ बनाने के लिए onCreate() फ़ंक्शन का इस्तेमाल करना होगा.

डिपेंडेंसी

फ़्रैगमेंट के साथ Kotlin DSL का इस्तेमाल करने के लिए, अपने ऐप्लिकेशन में नीचे दी गई डिपेंडेंसी जोड़ें build.gradle फ़ाइल:

ग्रूवी

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")
}

ग्राफ़ बनाना

यहां एक सामान्य उदाहरण दिया गया है, जो सनफ़्लावर ऐप्लिकेशन है. इसके लिए उदाहरण के लिए, हमारे दो डेस्टिनेशन हैं: home और plant_detail. home डेस्टिनेशन उस समय मौजूद होता है, जब उपयोगकर्ता पहली बार ऐप्लिकेशन लॉन्च करता है. यह मंज़िल उपयोगकर्ता के बगीचे से पौधों की सूची दिखाता है. जब उपयोगकर्ता इनमें से कोई एक चुनता है ऐप्लिकेशन, plant_detail डेस्टिनेशन पर नेविगेट करता है.

पहली इमेज में, इन डेस्टिनेशन के साथ-साथ वे आर्ग्युमेंट भी दिखाए गए हैं जो ऐप्लिकेशन, plant_detail डेस्टिनेशन और to_plant_detail कार्रवाई का इस्तेमाल करता है home से plant_detail तक जाने के लिए.

Sunflower ऐप्लिकेशन में दो डेस्टिनेशन हैं और एक ऐसी कार्रवाई
            उन्हें जोड़ता है.
पहली इमेज. Sunflower ऐप्लिकेशन के दो डेस्टिनेशन हैं, home और plant_detail. साथ ही, इस कार्रवाई को उन्हें जोड़ता है.

Kotlin DSL Nav ग्राफ़ को होस्ट करना

अपने ऐप्लिकेशन का नेविगेशन ग्राफ़ बनाने से पहले, आपको ग्राफ़. यह उदाहरण फ़्रैगमेंट का इस्तेमाल करता है, इसलिए यह ग्राफ़ को NavHostFragment इसके अंदर FragmentContainerView:

<!-- 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() के हिस्से के तौर पर सेट किया जा सके गतिविधि में मौजूद हैं.

एक्सएमएल में, कोई कार्रवाई एक या ज़्यादा आर्ग्युमेंट के साथ डेस्टिनेशन आईडी को जोड़ती है. हालांकि, नेविगेशन DSL का उपयोग करते समय रूट में बताया जा सकता है. इसका मतलब है कि डीएसएल का इस्तेमाल करते समय, किसी तरह की कार्रवाई करने की ज़रूरत नहीं होती.

अगला चरण वे रास्ते निर्धारित करना है, जिनका उपयोग आप अपने ग्राफ़.

अपने ग्राफ़ के लिए रूट बनाना

एक्सएमएल पर आधारित नेविगेशन ग्राफ़ को अलग-अलग हिस्से के तौर पर पार्स किया गया है Android बिल्ड प्रोसेस के बारे में ज़्यादा जानें. हर id के लिए, न्यूमेरिक (संख्या वाला) कॉन्स्टेंट बनाया जाता है एट्रिब्यूट की वैल्यू सबमिट करें. बिल्ड टाइम के दौरान जनरेट किए गए ये स्टैटिक आईडी, रनटाइम के दौरान आपका नेविगेशन ग्राफ़ बनाते समय उपलब्ध होता है, ताकि नेविगेशन DSL क्रम से लगाने की सुविधा का इस्तेमाल करता है के बजाय आईडी. हर रास्ता एक खास टाइप से दिखाया जाता है.

आर्ग्युमेंट के साथ काम करते समय, इन्हें रूट में बनाया जाता है type हैं. इससे आपको टाइप सेफ़्टी मिल जाती है .

@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 क्लास जो इस डेस्टिनेशन का यूज़र इंटरफ़ेस (यूआई) उपलब्ध कराता है. इसे सेट करने से वही असर होगा जो तय किए गए फ़्रैगमेंट डेस्टिनेशन पर android:name एट्रिब्यूट सेट करना करने के लिए कहा जा सकता है.

दूसरा, रास्ता. यह सीरियल नंबर वाला ऐसा टाइप होना चाहिए जो Any से बड़ा हो. यह इसमें ऐसे कोई नेविगेशन आर्ग्युमेंट होने चाहिए जिनका इस्तेमाल इस डेस्टिनेशन में किया जाएगा, और उनके प्रकार.

यह फ़ंक्शन अतिरिक्त कॉन्फ़िगरेशन के लिए, विकल्प के तौर पर एक Lambda फ़ंक्शन भी स्वीकार करता है, जैसे गंतव्य लेबल और साथ ही साथ कस्टम कॉन्फ़िगरेशन के लिए एम्बेड किए गए बिल्डर फ़ंक्शन आर्ग्युमेंट और डीप लिंक का इस्तेमाल करें.

आखिर में, 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 डेस्टिनेशन, जिनमें से हर एक की अपनी अलग जगह है इनलाइन एक्सटेंशन फ़ंक्शन, GA4 प्रॉपर्टी को बनाने और कॉन्फ़िगर करने के लिए उपलब्ध है गंतव्य.

फ़्रैगमेंट डेस्टिनेशन

कॉन्टेंट बनाने fragment() DSL फ़ंक्शन को यूज़र इंटरफ़ेस (यूआई) और खास तौर पर इस मंज़िल की पहचान करने के लिए, लैम्डा के बाद आने वाले रास्ते के टाइप का इस्तेमाल किया गया है यहां अतिरिक्त कॉन्फ़िगरेशन दिया जा सकता है. Kotlin DSL ग्राफ़ सेक्शन के साथ.

fragment<MyFragment, MyRoute> {
   label = getString(R.string.fragment_title)
   // custom argument types, deepLinks
}

गतिविधि की जगह

कॉन्टेंट बनाने activity() DSL फ़ंक्शन रूट के लिए एक प्रकार पैरामीटर लेता है, लेकिन उसे लागू करने वाली गतिविधि की कोई भी क्लास शामिल हो सकती है. इसके बजाय, आप वैकल्पिक activityClass को मॉडल को एक्ज़ीक्यूट करने की सुविधा मिलती है. इस सुविधा की मदद से, इनके लिए गतिविधि का डेस्टिनेशन तय किया जा सकता है एक ऐसी गतिविधि जिसे इंप्लिसिट वैल्यू का इस्तेमाल करके लॉन्च किया जाना चाहिए इंटेंट होता है, जिसमें अश्लील गतिविधि क्लास का कोई मतलब नहीं रह जाता. फ़्रैगमेंट डेस्टिनेशन की तरह, इसमें आपके पास कोई लेबल, कस्टम आर्ग्युमेंट, और डीप लिंक कॉन्फ़िगर करें.

activity<MyRoute> {
   label = getString(R.string.activity_title)
   // custom argument types, deepLinks...

   activityClass = MyActivity::class
}

कॉन्टेंट बनाने navigation() नेस्ट किया गया नेविगेशन बनाने के लिए, DSL फ़ंक्शन का इस्तेमाल किया जा सकता है ग्राफ़ देखें. यह फ़ंक्शन एक टाइप लेता है इस ग्राफ़ को असाइन करने के लिए रूट का पैरामीटर. इसमें दो तर्क भी होते हैं: ग्राफ़ के शुरुआती डेस्टिनेशन का रूट है, और लैम्डा को आगे जाने के लिए ग्राफ़ को कॉन्फ़िगर करें. मान्य एलिमेंट में अन्य डेस्टिनेशन, कस्टम आर्ग्युमेंट शामिल हैं टाइप, डीप लिंक, और डेस्टिनेशन. यह लेबल, नेविगेशन ग्राफ़ को यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट से बाइंड करने में काम का हो सकता है. इसके लिए, नीचे दिए गए तरीके का इस्तेमाल किया जा सकता है 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 क्लास के लिए किया जाता है. ज़रूरी तर्क ये हैं को शून्य नहीं हो सकने वाले टाइप के तौर पर बताया गया है. साथ ही, वैकल्पिक आर्ग्युमेंट को डिफ़ॉल्ट वैल्यू.

रूट और उनके आर्ग्युमेंट को दिखाने का मुख्य तरीका स्ट्रिंग है आधारित. रूट को मॉडल करने के लिए स्ट्रिंग का इस्तेमाल करने पर, नेविगेशन की स्थिति सेव की जाती है और कॉन्फ़िगरेशन के दौरान डिस्क से पुनर्स्थापित किया गया बदलाव और सिस्टम से शुरू की गई प्रोसेस मौत. इस वजह से, हर नेविगेशन आर्ग्युमेंट को क्रम से लगाया जाना चाहिए. इसका मतलब है कि उसमें तरीका, जो आर्ग्युमेंट वैल्यू के इन-मेमोरी प्रज़ेंटेशन को 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

डीप लिंक

डीप लिंक किसी भी डेस्टिनेशन पर ठीक वैसे ही जोड़े जा सकते हैं जैसे कि एक्सएमएल से होने पर किए जाते हैं नेविगेशन ग्राफ़. डीप लिंक बनाना डेस्टिनेशन के लिए, प्रोसेस पर लागू होते हैं Kotlin DSL का इस्तेमाल करके डीप लिंक बनाया जा सकता है.

इंप्लिसिट डीप लिंक बनाते समय हालांकि, आपके पास ऐसा एक्सएमएल नेविगेशन रिसॉर्स नहीं है जिसका विश्लेषण किया जा सके <deepLink> एलिमेंट. इसलिए, यूआरएल के साथ <nav-graph> तत्व आपकी AndroidManifest.xml फ़ाइल में मौजूद होना चाहिए और इसके बजाय इंटेंट आपकी गतिविधि के लिए फ़िल्टर इस्तेमाल कर सकते हैं. मकसद आपने जो फ़िल्टर दिया है वह इसके बेस पाथ, कार्रवाई, और mimetype से मेल खाना चाहिए आपके ऐप्लिकेशन के डीप लिंक.

अंदर deepLink फ़ंक्शन को कॉल करके किसी गंतव्य में डीप लिंक जोड़े जाते हैं गंतव्य का Lambda फ़ंक्शन. यह रूट को पैरामीटर वाले टाइप के तौर पर स्वीकार करता है और डीप लिंक के लिए इस्तेमाल किए गए यूआरएल के बेस पाथ के लिए पैरामीटर basePath.

कोई कार्रवाई और mimetype जोड़ने के लिए, आप इनका इस्तेमाल भी कर सकते हैं: deepLinkBuilder पीछे Lambda फ़ंक्शन.

नीचे दिया गया उदाहरण, Home डेस्टिनेशन के लिए डीप लिंक यूआरआई बनाता है.

@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/*"
  }
}

यूआरआई फ़ॉर्मैट

डीप लिंक यूआरआई फ़ॉर्मैट, रूट के फ़ील्ड से अपने-आप जनरेट होता है इसके लिए, यहां दिए गए नियमों का पालन करें:

  • ज़रूरी पैरामीटर, पाथ पैरामीटर के तौर पर जोड़े गए हैं (उदाहरण: /{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,
)

का जनरेट किया गया यूआरआई फ़ॉर्मैट है:

basePath/{id}/{name}/?colors={color1}&colors={color2}&latinName={latinName}

जोड़े जा सकने वाले डीप लिंक की कोई सीमा नहीं है. हर बार कॉल करने पर deepLink() उस सूची में एक नया डीप लिंक जोड़ा जाता है जिसे उस डेस्टिनेशन के लिए मैनेज किया जाता है.

सीमाएं

Safe Args प्लगिन यह Kotlin DSL के साथ काम नहीं करती, क्योंकि प्लगिन इसके लिए एक्सएमएल रिसॉर्स फ़ाइलों को खोजता है Directions और Arguments क्लास जनरेट करें.