डेटा को एक डेस्टिनेशन से दूसरे डेस्टिनेशन पर भेजें

नेविगेशन की मदद से, किसी डेस्टिनेशन के लिए आर्ग्युमेंट तय करके, नेविगेशन ऑपरेशन में डेटा अटैच किया जा सकता है. उदाहरण के लिए, उपयोगकर्ता प्रोफ़ाइल डेस्टिनेशन, उपयोगकर्ता आईडी के आधार पर यह तय कर सकता है कि किस उपयोगकर्ता को दिखाना है.

आम तौर पर, आपको डेस्टिनेशन के बीच कम से कम डेटा भेजना चाहिए. उदाहरण के लिए, किसी ऑब्जेक्ट को वापस पाने के लिए, आपको ऑब्जेक्ट के बजाय कुंजी पास करनी चाहिए. ऐसा इसलिए, क्योंकि Android पर सेव किए गए सभी स्टेटस के लिए कुल जगह सीमित होती है. अगर आपको ज़्यादा डेटा पास करना है, तो ViewModel की खास जानकारी में बताए गए तरीके के हिसाब से, ViewModel का इस्तेमाल करें.

डेस्टिनेशन के आर्ग्युमेंट के बारे में बताएं

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

  1. नेविगेशन एडिटर में, उस डेस्टिनेशन पर क्लिक करें जिसे आर्ग्युमेंट मिलता है.
  2. एट्रिब्यूट पैनल में, जोड़ें (+) पर क्लिक करें.
  3. इसके बाद, दिखने वाली आर्ग्युमेंट लिंक जोड़ें विंडो में, आर्ग्युमेंट का नाम, आर्ग्युमेंट टाइप, और यह जानकारी डालें कि आर्ग्युमेंट में वैल्यू डालना ज़रूरी है या नहीं. साथ ही, ज़रूरत पड़ने पर डिफ़ॉल्ट वैल्यू डालें.
  4. जोड़ें पर क्लिक करें. ध्यान दें कि आर्ग्युमेंट अब एट्रिब्यूट पैनल में आर्ग्युमेंट सूची में दिखता है.
  5. इसके बाद, उस कार्रवाई पर क्लिक करें जो आपको इस डेस्टिनेशन पर ले जाती है. एट्रिब्यूट पैनल में, आपको अब आर्ग्युमेंट की डिफ़ॉल्ट वैल्यू सेक्शन में, जोड़ा गया नया आर्ग्युमेंट दिखेगा.
  6. आपको यह भी दिख सकता है कि आर्ग्युमेंट को एक्सएमएल में जोड़ा गया था. एक्सएमएल व्यू पर टॉगल करने के लिए, टेक्स्ट टैब पर क्लिक करें. साथ ही, ध्यान दें कि आपका आर्ग्युमेंट उस डेस्टिनेशन में जोड़ा गया है जिसमें आर्ग्युमेंट मिलता है. इसका एक उदाहरण यहां दिया गया है:

     <fragment android:id="@+id/myFragment" >
         <argument
             android:name="myArg"
             app:argType="integer"
             android:defaultValue="0" />
     </fragment>
    

आर्ग्युमेंट के वे टाइप जो इसके साथ काम करते हैं

नेविगेशन लाइब्रेरी में, इन तरह के आर्ग्युमेंट इस्तेमाल किए जा सकते हैं:

टाइप app:argType का सिंटैक्स डिफ़ॉल्ट वैल्यू के लिए सहायता रूट के हिसाब से वैल्यू न होने पर भी काम करता है
पूर्णांक app:argType="integer" हां हां नहीं
फ़्लोट app:argType="float" हां हां नहीं
ज़्यादा समय के लिए app:argType="long" हां - डिफ़ॉल्ट वैल्यू हमेशा 'L' सफ़िक्स के साथ खत्म होनी चाहिए. उदाहरण के लिए, "123L". हां नहीं
बूलियन app:argType="boolean" हां - "सही" या "गलत" हां नहीं
स्ट्रिंग app:argType="string" हां हां हां
संसाधन का रेफ़रंस app:argType="reference" हां - डिफ़ॉल्ट वैल्यू, "@resourceType/resourceName" (उदाहरण के लिए, "@style/myCustomStyle") या "0" के तौर पर होनी चाहिए हां नहीं
कस्टम Parcelable app:argType="<type>", जहां <type>, Parcelable की पूरी तरह क्वालिफ़ाइड क्लास का नाम है "@null" की डिफ़ॉल्ट वैल्यू के साथ काम करता है. अन्य डिफ़ॉल्ट वैल्यू के साथ काम नहीं करता. नहीं हां
कस्टम Serializable app:argType="<type>", जहां <type>, Serializable की पूरी तरह क्वालिफ़ाइड क्लास का नाम है "@null" की डिफ़ॉल्ट वैल्यू के साथ काम करता है. अन्य डिफ़ॉल्ट वैल्यू के साथ काम नहीं करता. नहीं हां
कस्टम Enum app:argType="<type>", जहां <type>, Enum का पूरी तरह क्वालिफ़ाइड नाम है हां - डिफ़ॉल्ट वैल्यू, बिना शर्त वाले नाम से मेल खानी चाहिए. उदाहरण के लिए, MyEnum.SUCCESS से मैच करने के लिए "SUCCESS". नहीं नहीं

अगर किसी आर्ग्युमेंट टाइप में शून्य वैल्यू का इस्तेमाल किया जा सकता है, तो android:defaultValue="@null" का इस्तेमाल करके, डिफ़ॉल्ट वैल्यू के तौर पर शून्य का एलान किया जा सकता है.

अपने आर्ग्युमेंट के साथ रूट, डीप लिंक, और यूआरआई को स्ट्रिंग से पार्स किया जा सकता है. जैसा कि पिछली टेबल में देखा गया है, Parcelables और Serializables जैसे कस्टम डेटा टाइप का इस्तेमाल करके ऐसा नहीं किया जा सकता. कस्टम जटिल डेटा को पास करने के लिए, डेटा को किसी दूसरी जगह सेव करें. जैसे, ViewModel या डेटाबेस. साथ ही, नेविगेट करते समय सिर्फ़ आइडेंटिफ़ायर पास करें. नेविगेशन पूरा होने के बाद, डेटा को नई जगह से वापस पाएं.

कस्टम टाइप में से किसी एक को चुनने पर, क्लास चुनें डायलॉग बॉक्स दिखता है. इसमें, आपको उस टाइप के लिए मिलती-जुलती क्लास चुनने के लिए कहा जाता है. प्रोजेक्ट टैब की मदद से, अपने मौजूदा प्रोजेक्ट से कोई क्लास चुनी जा सकती है.

<inferred type> चुनकर, नेविगेशन लाइब्रेरी को दी गई वैल्यू के आधार पर टाइप तय करने के लिए कहा जा सकता है.

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

  • एनम के ऐरे और रिसॉर्स रेफ़रंस के ऐरे काम नहीं करते.
  • ऐरे में, शून्य वैल्यू का इस्तेमाल किया जा सकता है. भले ही, इस्तेमाल किए जा रहे टाइप में शून्य वैल्यू का इस्तेमाल किया जा सकता हो या नहीं. उदाहरण के लिए, app:argType="integer[]" का इस्तेमाल करने पर, app:nullable="true" का इस्तेमाल करके यह बताया जा सकता है कि कोई शून्य ऐरे पास करना स्वीकार किया जा सकता है.
  • ऐरे में सिर्फ़ एक डिफ़ॉल्ट वैल्यू, "@null" का इस्तेमाल किया जा सकता है. ऐरे में कोई दूसरी डिफ़ॉल्ट वैल्यू नहीं दी जा सकती.

किसी ऐक्शन में डेस्टिनेशन आर्ग्युमेंट को बदलना

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

यहां दिए गए एक्सएमएल में, एक ऐसी कार्रवाई के बारे में बताया गया है जिसमें एक आर्ग्युमेंट दिया गया है. यह आर्ग्युमेंट, पिछले उदाहरण में दिए गए डेस्टिनेशन-लेवल के आर्ग्युमेंट को बदल देता है:

<action android:id="@+id/startMyFragment"
    app:destination="@+id/myFragment">
    <argument
        android:name="myArg"
        app:argType="integer"
        android:defaultValue="1" />
</action>

टाइप सेफ़्टी के साथ डेटा भेजने के लिए, Safe Args का इस्तेमाल करना

नेविगेशन कॉम्पोनेंट में Safe Args नाम का Gradle प्लग इन होता है. यह टाइप से सुरक्षित नेविगेशन और जुड़े आर्ग्युमेंट के ऐक्सेस के लिए, आसान ऑब्जेक्ट और बिल्डर क्लास जनरेट करता है. डेटा को नेविगेट करने और भेजने के लिए, Safe Args का सुझाव दिया जाता है, क्योंकि इससे टाइप सेफ़्टी बनी रहती है.

अगर Gradle का इस्तेमाल नहीं किया जा रहा है, तो SafeArgs प्लग इन का इस्तेमाल नहीं किया जा सकता. ऐसे मामलों में, सीधे डेटा पास करने के लिए, बंडल का इस्तेमाल किया जा सकता है.

अपने प्रोजेक्ट में Safe Args जोड़ने के लिए, सबसे ऊपर के लेवल की build.gradle फ़ाइल में यह classpath शामिल करें:

Groovy

buildscript {
    repositories {
        google()
    }
    dependencies {
        def nav_version = "2.8.4"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
    }
}

Kotlin

buildscript {
    repositories {
        google()
    }
    dependencies {
        val nav_version = "2.8.4"
        classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version")
    }
}

आपको उपलब्ध दो प्लग इन में से किसी एक को भी लागू करना होगा.

Java या Java और Kotlin, दोनों मॉड्यूल के लिए सही Java भाषा कोड जनरेट करने के लिए, अपने ऐप्लिकेशन या मॉड्यूल की build.gradle फ़ाइल में यह लाइन जोड़ें:

Groovy

plugins {
  id 'androidx.navigation.safeargs'
}

Kotlin

plugins {
    id("androidx.navigation.safeargs")
}

इसके अलावा, सिर्फ़ Kotlin मॉड्यूल के लिए सही Kotlin कोड जनरेट करने के लिए, ये जोड़ें:

Groovy

plugins {
  id 'androidx.navigation.safeargs.kotlin'
}

Kotlin

plugins {
    id("androidx.navigation.safeargs.kotlin")
}

AndroidX पर माइग्रेट करने के मुताबिक, आपकी gradle.properties फ़ाइल में android.useAndroidX=true होना चाहिए.

Safe Args चालू करने के बाद, जनरेट किए गए कोड में हर कार्रवाई के लिए, यहां दी गई टाइप सेफ़ क्लास और तरीके शामिल होते हैं. साथ ही, ये हर भेजने और पाने वाले डेस्टिनेशन के साथ भी होते हैं.

  • हर उस डेस्टिनेशन के लिए एक क्लास बनाई जाती है जहां कोई ऐक्शन शुरू होता है. इस क्लास का नाम, ऑरिजिन डेस्टिनेशन का नाम होता है. इसमें "निर्देश" शब्द जोड़ा जाता है. उदाहरण के लिए, अगर ऑरिजिन डेस्टिनेशन SpecifyAmountFragment नाम का कोई फ़्रैगमेंट है, तो जनरेट की गई क्लास को SpecifyAmountFragmentDirections कहा जाता है.

    इस क्लास में, ऑरिजिन डेस्टिनेशन में तय किए गए हर ऐक्शन के लिए एक मेथड होता है.

  • आर्ग्युमेंट पास करने के लिए इस्तेमाल किए गए हर ऐक्शन के लिए, एक इनर क्लास बनाई जाती है, जिसका नाम ऐक्शन पर आधारित होता है. उदाहरण के लिए, अगर कार्रवाई का नाम confirmationAction, है, तो क्लास का नाम ConfirmationAction होगा. अगर आपकी कार्रवाई में defaultValue के बिना आर्ग्युमेंट शामिल हैं, तो आर्ग्युमेंट की वैल्यू सेट करने के लिए, उससे जुड़ी ऐक्शन क्लास का इस्तेमाल करें.

  • डेटा पाने वाले डेस्टिनेशन के लिए एक क्लास बनाई जाती है. इस क्लास का नाम, "Args" शब्द के साथ जोड़े गए डेस्टिनेशन का नाम होता है. उदाहरण के लिए, अगर डेस्टिनेशन फ़्रैगमेंट का नाम ConfirmationFragment, है, तो जनरेट की गई क्लास को ConfirmationFragmentArgs कहा जाता है. आर्ग्युमेंट वापस पाने के लिए, इस क्लास के fromBundle() तरीके का इस्तेमाल करें.

नीचे दिए गए उदाहरण में, इन तरीकों का इस्तेमाल करके आर्ग्युमेंट सेट करने और उसे navigate() के तरीके में पास करने का तरीका बताया गया है:

Kotlin

override fun onClick(v: View) {
   val amountTv: EditText = view!!.findViewById(R.id.editTextAmount)
   val amount = amountTv.text.toString().toInt()
   val action = SpecifyAmountFragmentDirections.confirmationAction(amount)
   v.findNavController().navigate(action)
}

Java

@Override
public void onClick(View view) {
   EditText amountTv = (EditText) getView().findViewById(R.id.editTextAmount);
   int amount = Integer.parseInt(amountTv.getText().toString());
   ConfirmationAction action =
           SpecifyAmountFragmentDirections.confirmationAction();
   action.setAmount(amount);
   Navigation.findNavController(view).navigate(action);
}

डेस्टिनेशन के कोड में, बंडल को वापस पाने और उसके कॉन्टेंट का इस्तेमाल करने के लिए, getArguments() तरीके का इस्तेमाल करें. -ktx डिपेंडेंसी का इस्तेमाल करते समय, Kotlin के उपयोगकर्ता, आर्ग्युमेंट ऐक्सेस करने के लिए by navArgs() प्रॉपर्टी डेलिगेट का भी इस्तेमाल कर सकते हैं.

Kotlin

val args: ConfirmationFragmentArgs by navArgs()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    val tv: TextView = view.findViewById(R.id.textViewAmount)
    val amount = args.amount
    tv.text = amount.toString()
}

Java

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    TextView tv = view.findViewById(R.id.textViewAmount);
    int amount = ConfirmationFragmentArgs.fromBundle(getArguments()).getAmount();
    tv.setText(amount + "");
}

ग्लोबल ऐक्शन के साथ Safe Args का इस्तेमाल करना

ग्लोबल ऐक्शन के साथ Safe Args का इस्तेमाल करते समय, आपको अपने रूट <navigation> एलिमेंट के लिए android:id वैल्यू देनी होगी, जैसा कि नीचे दिए गए उदाहरण में दिखाया गया है:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/main_nav"
            app:startDestination="@id/mainFragment">

    ...

</navigation>

नेविगेशन, <navigation> एलिमेंट के लिए Directions क्लास जनरेट करता है, जो android:id वैल्यू पर आधारित होती है. उदाहरण के लिए, अगर आपके पास android:id=@+id/main_nav वाला <navigation> एलिमेंट है, तो जनरेट की गई क्लास को MainNavDirections कहा जाता है. <navigation> एलिमेंट में मौजूद सभी डेस्टिनेशन में, उनसे जुड़ी सभी ग्लोबल कार्रवाइयों को ऐक्सेस करने के लिए, पिछले सेक्शन में बताए गए तरीकों का इस्तेमाल करके जनरेट किए गए तरीके होते हैं.

बंडल ऑब्जेक्ट की मदद से, डेटा को एक डेस्टिनेशन से दूसरे डेस्टिनेशन पर भेजना

अगर Gradle का इस्तेमाल नहीं किया जा रहा है, तो भी Bundle ऑब्जेक्ट का इस्तेमाल करके, डेस्टिनेशन के बीच आर्ग्युमेंट पास किए जा सकते हैं. Bundle ऑब्जेक्ट बनाएं और उसे navigate() का इस्तेमाल करके डेस्टिनेशन पर भेजें, जैसा कि इस उदाहरण में दिखाया गया है:

Kotlin

val bundle = bundleOf("amount" to amount)
view.findNavController().navigate(R.id.confirmationAction, bundle)

Java

Bundle bundle = new Bundle();
bundle.putString("amount", amount);
Navigation.findNavController(view).navigate(R.id.confirmationAction, bundle);

डेस्टिनेशन के कोड में, Bundle को वापस पाने और उसके कॉन्टेंट का इस्तेमाल करने के लिए, getArguments() तरीके का इस्तेमाल करें:

Kotlin

val tv = view.findViewById<TextView>(R.id.textViewAmount)
tv.text = arguments?.getString("amount")

Java

TextView tv = view.findViewById(R.id.textViewAmount);
tv.setText(getArguments().getString("amount"));

डेटा को स्टार्ट डेस्टिनेशन पर भेजना

अपने ऐप्लिकेशन के स्टार्ट डेस्टिनेशन में डेटा भेजा जा सकता है. सबसे पहले, आपको साफ़ तौर पर ऐसा Bundle बनाना होगा जिसमें डेटा हो. इसके बाद, Bundle को स्टार्ट डेस्टिनेशन पर भेजने के लिए, इनमें से किसी एक तरीके का इस्तेमाल करें:

  • अगर NavHost को प्रोग्राम के हिसाब से बनाया जा रहा है, तो NavHostFragment.create(R.navigation.graph, args) को कॉल करें. यहां args वह Bundle है जिसमें आपका डेटा होता है.
  • इसके अलावा, NavController.setGraph() के इनमें से किसी एक ओवरलोड को कॉल करके, शुरू होने के डेस्टिनेशन के आर्ग्युमेंट सेट किए जा सकते हैं:

शुरुआती डेस्टिनेशन में डेटा वापस पाने के लिए, Fragment.getArguments() को कॉल करें.

ProGuard के बारे में ज़रूरी बातें

अगर कोड को छोटा किया जा रहा है, तो आपको कोड को छोटा करने की प्रोसेस के तहत, Parcelable, Serializable, और Enum क्लास के नामों को उलझाने से रोकना होगा. ऐसा करने के दो तरीके हैं:

  • @Keep एनोटेशन का इस्तेमाल करना.
  • नामों को सेव रखने के नियमों का इस्तेमाल करें.

नीचे दिए गए सब-सेक्शन में इन तरीकों के बारे में बताया गया है.

@Keep एनोटेशन का इस्तेमाल करना

इस उदाहरण में, मॉडल क्लास की परिभाषाओं में @Keep एनोटेशन जोड़े गए हैं:

Kotlin

@Keep class ParcelableArg : Parcelable { ... }

@Keep class SerializableArg : Serializable { ... }

@Keep enum class EnumArg { ... }

Java

@Keep public class ParcelableArg implements Parcelable { ... }

@Keep public class SerializableArg implements Serializable { ... }

@Keep public enum EnumArg { ... }

'नामों को बनाए रखें' नियमों का इस्तेमाल करना

अपनी proguard-rules.pro फ़ाइल में keepnames नियम भी जोड़े जा सकते हैं, जैसा कि इस उदाहरण में दिखाया गया है:

proguard-rules.pro

...

-keepnames class com.path.to.your.ParcelableArg
-keepnames class com.path.to.your.SerializableArg
-keepnames class com.path.to.your.EnumArg

...

अन्य संसाधन

नेविगेशन के बारे में ज़्यादा जानने के लिए, यहां दिए गए अन्य संसाधन देखें.

कोडलैब

वीडियो