গন্তব্যের মধ্যে ডেটা পাস করা

নেভিগেশন আপনাকে কোনও গন্তব্যের জন্য আর্গুমেন্ট সংজ্ঞায়িত করে নেভিগেশন অপারেশনে ডেটা অ্যাটাচ করতে দেয়। যেমন, ব্যবহারকারীর প্রোফাইল ডেস্টিনেশন, কোন ব্যবহারকারীকে দেখাতে হবে তা নির্ধারণ করতে ব্যবহারকারীর আইডি আর্গুমেন্ট নিতে পারে।

সাধারণত, ডেস্টিনেশনের মধ্যে ডেটার ন্যূনতম পরিমাণ পাস করার জন্য আপনাকে দৃঢ়ভাবে পছন্দ করতে হবে। যেমন, কোনও অবজেক্ট ফিরিয়ে আনার জন্য অবজেক্টটি পাস করার পরিবর্তে আপনার একটি কী পাস করা উচিত, কারণ Android-এ সব সেভ করা অবস্থার জন্য মোট স্পেস সীমিত। আপনাকে যদি প্রচুর পরিমাণে ডেটা পাস করতে হয়, তাহলে ViewModel ওভারভিউ-এ যেমন বর্ণনা করা হয়েছে, সেই অনুযায়ী ViewModel ব্যবহার করুন।

গন্তব্য আর্গুমেন্ট ব্যাখ্যা করুন

গন্তব্যগুলির মধ্যে ডেটা পাস করতে, প্রথমে এই ধাপগুলি অনুসরণ করে যে গন্তব্য এটি গ্রহণ করে তাতে যোগ করে আর্গুমেন্টটি সংজ্ঞায়িত করুন:

  1. নেভিগেশন এডিটর-এ, যে গন্তব্য আর্গুমেন্ট গ্রহণ করে সেটিতে ক্লিক করুন।
  2. অ্যাট্রিবিউট প্যানেলে, যোগ করুন (+) বিকল্পে ক্লিক করুন।
  3. যে আর্গুমেন্ট লিঙ্ক যোগ করুন উইন্ডোটি দেখা যাবে, সেখানে আর্গুমেন্টের নাম, আর্গুমেন্টের ধরন, আর্গুমেন্টটি নালেবেল কিনা এবং প্রয়োজন হলে ডিফল্ট ভ্যালু লিখুন।
  4. যোগ করুন বিকল্পে ক্লিক করুন। লক্ষ্য করুন যে আর্গুমেন্টটি এখন অ্যাট্রিবিউট প্যানেলের আর্গুমেন্ট তালিকায় দেখা যাচ্ছে।
  5. এরপর, সংশ্লিষ্ট অ্যাকশনে ক্লিক করুন যা আপনাকে এই গন্তব্যে নিয়ে যাবে। অ্যাট্রিবিউট প্যানেলে, আপনি এখন আর্গুমেন্টের ডিফল্ট ভ্যালু বিভাগে আপনার নতুন যোগ করা আর্গুমেন্ট দেখতে পাবেন।
  6. আপনি আরও দেখতে পাবেন যে XML-এ আর্গুমেন্ট যোগ করা হয়েছে। XML ভিউতে টগল করতে টেক্সট ট্যাবে ক্লিক করুন এবং লক্ষ্য করুন যে আপনার আর্গুমেন্টটি আর্গুমেন্ট গ্রহণকারী ডেস্টিনেশনে যোগ করা হয়েছে। নিচে একটি উদাহরণ দেখানো হল:

     <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" হ্যাঁ - "true" বা "false" হ্যাঁ না
স্ট্রিং app:argType="string" হ্যাঁ হ্যাঁ হ্যাঁ
রিসোর্স রেফারেন্স app:argType="reference" হ্যাঁ - ডিফল্ট ভ্যালু অবশ্যই "@resourceType/resourceName" (যেমন, "@style/myCustomStyle") বা "0" ফর্ম্যাটে হতে হবে হ্যাঁ না
কাস্টম পার্সেলযোগ্য app:argType="<type>", যেখানে <type> হল Parcelable-এর সম্পূর্ণ-যোগ্য ক্লাস নাম "@null" ডিফল্ট ভ্যালু হিসেবে কাজ করে। অন্যান্য ডিফল্ট ভ্যালু কাজ করে না। না হ্যাঁ
কাস্টম সিরিয়ালাইজেবল app:argType="<type>", যেখানে <type> হল Serializable-এর সম্পূর্ণ-যোগ্য ক্লাস নাম "@null"-এর ডিফল্ট ভ্যালু কাজ করে। অন্যান্য ডিফল্ট ভ্যালু কাজ করে না। না হ্যাঁ
কাস্টম Enum app:argType="<type>", যেখানে <type> হল enum-এর সম্পূর্ণ-যোগ্য নাম হ্যাঁ - ডিফল্ট ভ্যালু অবশ্যই আনকোয়ালিফায়েড নামের সাথে মিলতে হবে (যেমন, MyEnum.SUCCESS-এর সাথে মিলতে "SUCCESS")। না না

কোনও আর্গুমেন্টের ধরন যদি ফাঁকা ভ্যালু সমর্থন করে, তাহলে আপনি android:defaultValue="@null" ব্যবহার করে ফাঁকা ডিফল্ট ভ্যালু ঘোষণা করতে পারেন।

স্ট্রিং থেকে রুট, ডিপ লিঙ্ক এবং আর্গুমেন্ট সহ URI পার্স করা যেতে পারে। পূর্ববর্তী সারণীতে যেমন দেখা গেছে, Parcelables এবং Serializables-এর মতো কাস্টম ডেটা টাইপ ব্যবহার করে এটি করা সম্ভব নয়। কাস্টম জটিল ডেটা পাস করতে, ViewModel বা ডেটাবেসের মতো অন্য কোথাও ডেটা স্টোর করুন এবং নেভিগেট করার সময় শুধুমাত্র একটি আইডেন্টিফায়ার পাস করুন; তারপর নেভিগেশন শেষ হওয়ার পরে নতুন লোকেশনে ডেটা ফিরিয়ে আনুন।

আপনি কাস্টম ধরনের মধ্যে থেকে কোনও একটি বেছে নিলে, ক্লাস বেছে নিন ডায়ালগ বক্স দেখানো হয় এবং সেই ধরনের জন্য সংশ্লিষ্ট ক্লাস বেছে নিতে প্রম্পট করা হয়। প্রোজেক্ট ট্যাব আপনাকে বর্তমান প্রোজেক্ট থেকে ক্লাস বেছে নিতে দেয়।

আপনি <inferred type> বেছে নিতে পারেন যাতে নেভিগেশন লাইব্রেরি প্রদত্ত ভ্যালুর উপর ভিত্তি করে ধরন নির্ধারণ করতে পারে।

আর্গুমেন্টটি বেছে নেওয়া Type ভ্যালুর অ্যারে হওয়া উচিত কিনা তা নির্দেশ করতে আপনি Array চেক করতে পারেন। এগুলি মনে রাখবেন:

  • enum-এর অ্যারে এবং রিসোর্স রেফারেন্সের অ্যারে কাজ করে না।
  • অ্যারে নালেবেল ভ্যালু সাপোর্ট করে, অন্তর্নিহিত ধরনের নালেবেল ভ্যালুর জন্য সাপোর্ট নির্বিশেষে। যেমন, app:argType="integer[]" ব্যবহার করলে আপনি app:nullable="true" ব্যবহার করে বোঝাতে পারবেন যে নাল অ্যারে পাস করা গ্রহণযোগ্য।
  • অ্যারেতে একটি ডিফল্ট ভ্যালু কাজ করে, "@null"। অ্যারেতে অন্য কোনও ডিফল্ট ভ্যালু কাজ করে না।

কোনও অ্যাকশনে ডেস্টিনেশন আর্গুমেন্ট ওভাররাইড করুন

গন্তব্য-লেভেল আর্গুমেন্ট এবং ডিফল্ট ভ্যালু সেইসব অ্যাকশন ব্যবহার করে যেগুলি গন্তব্যে নেভিগেট করে। প্রয়োজন হলে, আপনি অ্যাকশন লেভেলে আর্গুমেন্ট নির্ধারণ করে, আর্গুমেন্টের ডিফল্ট ভ্যালু ওভাররাইড করতে পারবেন (অথবা আগে থেকে না থাকলে, একটি সেট করতে পারবেন)। এই আর্গুমেন্টটি অবশ্যই গন্তব্যে ঘোষিত আর্গুমেন্টের মতো একই নাম এবং প্রকারের হতে হবে।

নিম্নলিখিত XML-এ এমন একটি আর্গুমেন্ট সহ অ্যাকশন ঘোষণা করা হয়েছে যা পূর্ববর্তী উদাহরণের গন্তব্য-লেভেল আর্গুমেন্টকে ওভাররাইড করে:

<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 ব্যবহার না করলে, Safe Args প্লাগ-ইন ব্যবহার করতে পারবেন না। এইসব ক্ষেত্রে, আপনি সরাসরি ডেটা পাস করতে Bundles ব্যবহার করতে পারবেন।

আপনার প্রোজেক্টে সেফ আর্গস (Safe Args) যোগ করতে, আপনার টপ লেভেল build.gradle ফাইলে নিম্নলিখিত classpath অন্তর্ভুক্ত করুন:

গ্রুভি

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

কোটলিন

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

আপনাকে উপলব্ধ দুটি প্লাগইনের মধ্যে একটি অবশ্যই প্রয়োগ করতে হবে।

জাভা অথবা জাভা ও কোটলিনের মিশ্র মডিউলের জন্য উপযুক্ত জাভা ল্যাঙ্গুয়েজ কোড তৈরি করতে, আপনার অ্যাপ বা মডিউলের build.gradle ফাইলে এই লাইনটি যোগ করুন:

গ্রুভি

plugins {
  id 'androidx.navigation.safeargs'
}

কোটলিন

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

বিকল্পভাবে, শুধুমাত্র কোটলিন মডিউলের জন্য উপযুক্ত কোটলিন কোড তৈরি করতে যোগ করুন:

গ্রুভি

plugins {
  id 'androidx.navigation.safeargs.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)
}

জাভা

@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()
}

জাভা

@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> এলিমেন্টের মধ্যে থাকা সব ডেস্টিনেশনে আগের বিভাগে বর্ণনা করা একই পদ্ধতি ব্যবহার করে সব সংশ্লিষ্ট গ্লোবাল অ্যাকশন অ্যাক্সেস করার জন্য জেনারেট করা পদ্ধতি আছে।

Bundle অবজেক্টের মাধ্যমে ডেস্টিনেশনের মধ্যে ডেটা পাস করা

আপনি Gradle ব্যবহার না করলেও, Bundle অবজেক্ট ব্যবহার করে গন্তব্যগুলির মধ্যে আর্গুমেন্ট পাস করতে পারবেন। Bundle অবজেক্ট তৈরি করুন এবং navigate() ব্যবহার করে এটি গন্তব্যে পাস করুন, যেমন নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

Kotlin

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

জাভা

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

জাভা

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 অ্যানোটেশন ব্যবহার করুন।
  • keepnames নিয়ম ব্যবহার করুন।

নিম্নলিখিত উপবিভাগে এই পদ্ধতিগুলি সম্পর্কে সংক্ষেপে বলা হয়েছে।

@Keep অ্যানোটেশন ব্যবহার করুন

নিম্নলিখিত উদাহরণটি মডেল ক্লাস সংজ্ঞায় @Keep অ্যানোটেশন যোগ করে:

Kotlin

@Keep class ParcelableArg : Parcelable { ... }

@Keep class SerializableArg : Serializable { ... }

@Keep enum class EnumArg { ... }

জাভা

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

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

@Keep public enum EnumArg { ... }

keepnames নিয়ম ব্যবহার করুন

এছাড়াও, আপনি 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

...

অতিরিক্ত রিসোর্স

নেভিগেশন সম্পর্কে আরও জানতে, নিম্নলিখিত অতিরিক্ত রিসোর্স দেখুন।

কোডল্যাবস

ভিডিও