Kotlin DSL का इस्तेमाल करके प्रोग्राम के हिसाब से ग्राफ़ बनाना

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

डिपेंडेंसी

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

ग्रूवी

dependencies {
    def nav_version = "2.7.7"

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

Kotlin

dependencies {
    val nav_version = "2.7.7"

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

ग्राफ़ बनाना

आइए, Sunflower ऐप्लिकेशन. इसके लिए उदाहरण के लिए, हमारे दो डेस्टिनेशन हैं: 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() के हिस्से के तौर पर सेट किया जाना चाहिए गतिविधि में मौजूद हैं.

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

अगला चरण कुछ स्थिरांक तय करना है, जिनका इस्तेमाल आपको एसेट की परिभाषा तय करते समय करना है. आपका ग्राफ़.

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

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

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

object nav_routes {
    const val home = "home"
    const val plant_detail = "plant_detail"
}

object nav_arguments {
    const val plant_id = "plant_id"
    const val plant_name = "plant_name"
}

कॉन्सटेंट तय करने के बाद, नेविगेशन पैनल बनाया जा सकता है ग्राफ़.

val navController = findNavController(R.id.nav_host_fragment)
navController.graph = navController.createGraph(
    startDestination = nav_routes.home
) {
    fragment<HomeFragment>(nav_routes.home) {
        label = resources.getString(R.string.home_title)
    }

    fragment<PlantDetailFragment>("${nav_routes.plant_detail}/{${nav_arguments.plant_id}}") {
        label = resources.getString(R.string.plant_detail_title)
        argument(nav_arguments.plant_id) {
            type = NavType.StringType
        }
    }
}

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

वह Fragment क्लास, जो हर डेस्टिनेशन के यूज़र इंटरफ़ेस (यूआई) को मैनेज करता है. साथ ही, इसे पैरामीटर वाले टाइप में पास किया जाता है ऐंगल ब्रैकेट (<>). इसका असर android:name को सेट करने जैसा ही होता है फ़्रैगमेंट डेस्टिनेशन पर एट्रिब्यूट, जिसे एक्सएमएल का इस्तेमाल करके तय किया जाता है.

आखिर में, स्टैंडर्ड यूआरएल का इस्तेमाल करके, home से plant_detail तक नेविगेट किया जा सकता है NavController.net() कॉल:

private fun navigateToPlant(plantId: String) {
   findNavController().navigate("${nav_routes.plant_detail}/$plantId")
}

PlantDetailFragment में, आर्ग्युमेंट की वैल्यू, उदाहरण के तौर पर दी गई जानकारी के हिसाब से हासिल की जा सकती है नीचे दिए गए उदाहरण में:

val plantId: String? = arguments?.getString(nav_arguments.plant_id)

नेविगेट करते समय आर्ग्युमेंट सप्लाई करने के तरीके का ब्यौरा डेस्टिनेशन आर्ग्युमेंट उपलब्ध कराना सेक्शन.

इस गाइड के बाकी हिस्से में, नेविगेशन ग्राफ़ के सामान्य एलिमेंट, डेस्टिनेशन, साथ ही, ग्राफ़ बनाते समय उन्हें इस्तेमाल करने का तरीका भी बताया जाएगा.

गंतव्य

Kotlin DSL तीन तरह के डेस्टिनेशन के लिए बिल्ट-इन सपोर्ट करता है: Fragment, Activity, और NavGraph डेस्टिनेशन, जिनमें से हर एक की अपनी अलग जगह है इनलाइन एक्सटेंशन फ़ंक्शन, GA4 प्रॉपर्टी को बनाने और कॉन्फ़िगर करने के लिए उपलब्ध है गंतव्य.

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

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

fragment<FragmentDestination>(nav_routes.route_name) {
   label = getString(R.string.fragment_title)
   // arguments, deepLinks
}

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

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

activity(nav_routes.route_name) {
   label = getString(R.string.activity_title)
   // arguments, deepLinks...

   activityClass = ActivityDestination::class
}

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

navigation("route_to_this_graph", nav_routes.home) {
   // label, other destinations, deep links
}

कस्टम डेस्टिनेशन के साथ काम करना

अगर आपको किसी नया गंतव्य प्रकार शामिल करता है, जो यह ऐप्लिकेशन सीधे Kotlin DSL का इस्तेमाल करता है, तो आपके पास इन डेस्टिनेशन को अपने Kotlin में जोड़ा जा सकता है addDestination() का इस्तेमाल करके 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
}

डेस्टिनेशन के आर्ग्युमेंट दिए जा रहे हैं

कोई भी डेस्टिनेशन, ऐसे आर्ग्युमेंट तय कर सकता है जो ज़रूरी नहीं या ज़रूरी नहीं हैं. कार्रवाइयाँ को इसका इस्तेमाल करके परिभाषित किया जा सकता है argument() NavDestinationBuilder पर फ़ंक्शन का इस्तेमाल करें, जो सभी के लिए बेस क्लास है डेस्टिनेशन बिल्डर के टाइप. यह फ़ंक्शन, आर्ग्युमेंट के नाम को स्ट्रिंग के तौर पर इस्तेमाल करता है साथ ही, एक Lambda फ़ंक्शन है, जिसका इस्तेमाल एक NavArgument.

Lambda फ़ंक्शन में, आर्ग्युमेंट डेटा टाइप को चुना जा सकता है. हालांकि, अगर ऐसा करना है, तो डिफ़ॉल्ट वैल्यू लागू हो और यह अमान्य हो या नहीं.

fragment<PlantDetailFragment>("${nav_routes.plant_detail}/{${nav_arguments.plant_id}}") {
    label = getString(R.string.plant_details_title)
    argument(nav_arguments.plant_id) {
        type = NavType.StringType
        defaultValue = getString(R.string.default_plant_id)
        nullable = true  // default false
    }
}

अगर defaultValue दिया गया है, तो टाइप का पता लगाया जा सकता है. अगर defaultValue और एक type दिया गया है, तो टाइप मैच होने चाहिए. ज़्यादा जानकारी के लिए, NavType के रेफ़रंस दस्तावेज़ उपलब्ध आर्ग्युमेंट टाइप की पूरी सूची.

कस्टम टाइप उपलब्ध कराना

कुछ टाइप, जैसे कि ParcelableType और SerializableType, रूट या डीप लिंक के ज़रिए इस्तेमाल की जाने वाली स्ट्रिंग से पार्स वैल्यू को पार्स करने की सुविधा नहीं है. ऐसा इसलिए होता है, क्योंकि रनटाइम के दौरान ये सेटिंग किसी रिफ़्लेक्शन पर निर्भर नहीं होती हैं. कस्टम सेगमेंट बनाकर NavType क्लास है, तो आप यह कंट्रोल कर सकते हैं कि आपके टाइप को रूट से किस तरह पार्स किया जाए या डीप लिंक. इसकी मदद से, Kotlin सीरियलाइजे़शन या अन्य लाइब्रेरी का इस्तेमाल किया जा सकता है, ताकि आप अपनी पसंद के मुताबिक बिना किसी बदलाव के, कोड में बदलने का तरीका और डिकोडिंग उपलब्ध करा सकें.

उदाहरण के लिए, ऐसी डेटा क्लास जो आपके खोज स्क्रीन, दोनों को लागू कर सकती है Serializable (यह कोड में बदलने/डिकोड करने की सुविधा) और Parcelize (डेटा सेव करने और वापस लाने की सुविधा के लिए) Bundle से):

@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>(nav_routes.plant_search) {
    label = getString(R.string.plant_search_title)
    argument(nav_arguments.search_parameters) {
        type = SearchParametersType
        defaultValue = SearchParameters("cactus", emptyList())
    }
}

NavType में हर फ़ील्ड के लिखने और पढ़ने, दोनों को इनकैप्सुलेट करता है, जो इसका मतलब है कि NavType का इस्तेमाल तब भी किया जाना चाहिए, जब आप डेस्टिनेशन की मदद से यह पक्का किया जा सकता है कि फ़ॉर्मैट मैच करते हों:

val params = SearchParameters("rose", listOf("available"))
val searchArgument = SearchParametersType.serializeAsValue(params)
navController.navigate("${nav_routes.plant_search}/$searchArgument")

इस पैरामीटर को डेस्टिनेशन के आर्ग्युमेंट से लिया जा सकता है:

val params: SearchParameters? = arguments?.getParcelable(nav_arguments.search_parameters)

डीप लिंक

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

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

अलग-अलग डीप लिंक किए गए हर एक के लिए, ज़्यादा सटीक deeplink दिया जा सकता है गंतव्य का उपयोग करके deepLink() DSL फ़ंक्शन. यह फ़ंक्शन, String वाले NavDeepLink को स्वीकार करता है यूआरआई पैटर्न की जानकारी देता है, String इंटेंट ऐक्शन को दिखाता है, और String, mimeType दिखाता है .

उदाहरण के लिए:

deepLink {
    uriPattern = "http://www.example.com/plants/"
    action = "android.intent.action.MY_ACTION"
    mimeType = "image/*"
}

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

एक ज़्यादा जटिल डीप लिंक स्थिति, जो पाथ और क्वेरी पर आधारित पैरामीटर नीचे दिखाए गए हैं:

val baseUri = "http://www.example.com/plants"

fragment<PlantDetailFragment>(nav_routes.plant_detail) {
   label = getString(R.string.plant_details_title)
   deepLink(navDeepLink {
    uriPattern = "${baseUri}/{id}"
   })
   deepLink(navDeepLink {
    uriPattern = "${baseUri}/{id}?name={plant_name}"
   })
}

Google Analytics 4 पर माइग्रेट करने के लिए, स्ट्रिंग इंटरपोलेशन .

सीमाएं

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

ज़्यादा जानें

नेविगेशन टाइप की सुरक्षा देखें इस पेज पर जाएं और यह जानें कि Kotlin DSL के लिए टाइप सेफ़्टी कैसे दी जाती है और नेविगेशन कंपोज़ कोड.