সাধারণ বিষয়গুলি বুঝে নিয়ে প্রয়োগ করা

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

নেভিগেশন স্টেট মডেল করা

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

সফ্টওয়্যার কীবোর্ডের অ্যাকশন বোতাম (একটি টিকচিহ্ন আইকন) লাল রঙ দিয়ে বৃত্তাকার করা হয়েছে।
ছবি ১. ব্যবহারকারীর নেভিগেশন ইভেন্টের সাথে ব্যাক স্ট্যাক কীভাবে পরিবর্তিত হয় তা ডায়াগ্রামে দেখানো হয়েছে।

ব্যাক স্ট্যাক তৈরি করা

Navigation 3-এ, ব্যাক স্ট্যাকে আসলে কোনও কন্টেন্ট থাকে না। পরিবর্তে, এতে কন্টেন্টের রেফারেন্স থাকে, যা কী নামে পরিচিত। কী যেকোনও ধরনের হতে পারে, তবে সাধারণত সহজ, সিরিয়ালাইজ করা যায় এমন ডেটা ক্লাস হয়। কন্টেন্টের পরিবর্তে রেফারেন্স ব্যবহার করলে নিচে উল্লেখ করা সুবিধাগুলি পাওয়া যায়:

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

Navigation 3 API-এর একটি মূল ধারণা হল, আপনি ব্যাক স্ট্যাকের মালিক। লাইব্রেরি:

  • আশা করা হয় যে আপনার ব্যাক স্ট্যাক একটি স্ন্যাপশট-স্টেট ব্যাকড List<T> হবে, যেখানে T হল আপনার ব্যাক স্ট্যাকের ধরন keys। আপনি Any ব্যবহার করতে পারেন অথবা আপনি নিজের, আরও শক্তিশালী-টাইপ করা কী প্রদান করতে পারেন। আপনি "পুশ" বা "পপ" শব্দগুলি দেখলে, বুঝতে হবে যে এর অন্তর্নিহিত প্রয়োগ হল কোনও তালিকার শেষ থেকে আইটেম যোগ করা বা সরানো।
  • আপনার ব্যাক স্ট্যাক পর্যবেক্ষণ করে এবং UI-তে এর অবস্থা দেখানোর জন্য NavDisplay ব্যবহার করে।

কী ও ব্যাক স্ট্যাক কীভাবে তৈরি করতে হয় এবং ব্যবহারকারীর নেভিগেশন ইভেন্টের উত্তরে ব্যাক স্ট্যাক কীভাবে পরিবর্তন করতে হয় তা নিচের উদাহরণ থেকে দেখুন:

// Define keys that will identify content
data object ProductList
data class ProductDetail(val id: String)

@Composable
fun MyApp() {

    // Create a back stack, specifying the key the app should start with
    val backStack = remember { mutableStateListOf<Any>(ProductList) }

    // Supply your back stack to a NavDisplay so it can reflect changes in the UI
    // ...more on this below...

    // Push a key onto the back stack (navigate forward), the navigation library will reflect the change in state
    backStack.add(ProductDetail(id = "ABC"))

    // Pop a key off the back stack (navigate back), the navigation library will reflect the change in state
    backStack.removeLastOrNull()
}

কন্টেন্টের কী সমাধান করা

NavEntry ব্যবহার করে নেভিগেশন ৩-এ কন্টেন্ট মডেল করা হয়, এটি একটি কম্পোজ করা যায় এমন ফাংশন যুক্ত ক্লাস। এটি একটি ডেস্টিনেশন - কন্টেন্টের একটি অংশ যা ব্যবহারকারী এগিয়ে যেতে এবং ফিরে আসতে পারেন।

NavEntry-এ মেটাডেটাও থাকতে পারে - কন্টেন্ট সম্পর্কে তথ্য। NavEntry-এর কন্টেন্ট কীভাবে দেখানো হবে তা নির্ধারণ করতে, NavDisplay-এর মতো কন্টেনার অবজেক্ট এই মেটাডেটা পড়তে পারে। যেমন, কোনও নির্দিষ্ট NavEntry-এর জন্য ডিফল্ট অ্যানিমেশন ওভাররাইড করতে মেটাডেটা ব্যবহার করা যেতে পারে। NavEntry metadata হল String কী থেকে Any ভ্যালুর ম্যাপ, যা বহুমুখী ডেটা স্টোরেজ প্রদান করে।

key-কে NavEntry-এ পরিবর্তন করতে, এন্ট্রি প্রদানকারী তৈরি করুন। এটি এমন একটি ফাংশন যা key গ্রহণ করে এবং সেই key-এর জন্য NavEntry রিটার্ন করে। NavDisplay তৈরি করার সময় এটি সাধারণত ল্যাম্বডা প্যারামিটার হিসেবে সংজ্ঞায়িত করা হয়।

এন্ট্রি প্রদানকারী তৈরি করার দুটি উপায় আছে, সরাসরি ল্যাম্বডা ফাংশন তৈরি করে অথবা entryProvider DSL ব্যবহার করে।

সরাসরি এন্ট্রি প্রদানকারী ফাংশন তৈরি করা

আপনি সাধারণত when স্টেটমেন্ট ব্যবহার করে একটি এন্ট্রি প্রদানকারী ফাংশন তৈরি করেন, যার মধ্যে আপনার প্রতিটি কী-এর জন্য একটি করে ব্রাঞ্চ থাকে।

entryProvider = { key ->
    when (key) {
        is ProductList -> NavEntry(key) { Text("Product List") }
        is ProductDetail -> NavEntry(
            key,
            metadata = mapOf("extraDataKey" to "extraDataValue")
        ) { Text("Product ${key.id} ") }

        else -> {
            NavEntry(Unit) { Text(text = "Invalid Key: $it") }
        }
    }
}

entryProvider DSL ব্যবহার করুন

entryProvider DSL আপনার ল্যাম্বডা ফাংশনকে সহজ করে তুলতে পারে, কারণ এর ফলে আপনাকে প্রতিটি কী ধরনের জন্য আলাদা আলাদা করে পরীক্ষা করতে হয় না এবং প্রতিটি কী ধরনের জন্য NavEntry তৈরি করতে হয় না। এর জন্য entryProvider বিল্ডার ফাংশন ব্যবহার করুন। এছাড়াও, কী খুঁজে না পাওয়া গেলে, এটি ডিফল্ট ফলব্যাক আচরণ (সমস্যা দেখানো) অন্তর্ভুক্ত করে।

entryProvider = entryProvider {
    entry<ProductList> { Text("Product List") }
    entry<ProductDetail>(
        metadata = mapOf("extraDataKey" to "extraDataValue")
    ) { key -> Text("Product ${key.id} ") }
}

স্নিপেট থেকে নিম্নলিখিত বিষয়গুলি মনে রাখবেন:

  • entry-এর মাধ্যমে প্রদত্ত ধরন ও কম্পোজ করার উপযুক্ত কন্টেন্ট সহ NavEntry নির্ধারণ করা হয়
  • entry, NavEntry.metadata সেট করার জন্য metadata প্যারামিটার নেয়

ব্যাক স্ট্যাক ডিসপ্লে করা

ব্যাক স্ট্যাক আপনার অ্যাপের নেভিগেশন স্টেটকে উপস্থাপন করে। ব্যাক স্ট্যাক পরিবর্তিত হলে, অ্যাপ UI-তে নতুন ব্যাক স্ট্যাকের অবস্থা দেখানো উচিত। Navigation 3-এ, a NavDisplay আপনার ব্যাক স্ট্যাক পর্যবেক্ষণ করে এবং সেই অনুযায়ী UI আপডেট করে। নিম্নলিখিত প্যারামিটার দিয়ে এটি তৈরি করুন:

  • আপনার ব্যাক স্ট্যাক - এটি SnapshotStateList<T> ধরনের হতে হবে, যেখানে T হল আপনার ব্যাক স্ট্যাক কী-এর ধরন। এটি একটি অবজার্ভেবল List যাতে এটি পরিবর্তন হলে NavDisplay-এর রিকম্পোজিশন ট্রিগার করে।
  • আপনার ব্যাক স্ট্যাকের কীগুলিকে NavEntry অবজেক্টে কনভার্ট করার জন্য একটি entryProvider।
  • ঐচ্ছিকভাবে, onBack প্যারামিটারে একটি ল্যাম্বডা প্রদান করুন। ব্যবহারকারী ব্যাক ইভেন্ট ট্রিগার করলে এটি কল করা হয়।

নিম্নলিখিত উদাহরণ থেকে কীভাবে NavDisplay তৈরি করতে হয় তা জানুন।

data object Home
data class Product(val id: String)

@Composable
fun NavExample() {

    val backStack = remember { mutableStateListOf<Any>(Home) }

    NavDisplay(
        backStack = backStack,
        onBack = { backStack.removeLastOrNull() },
        entryProvider = { key ->
            when (key) {
                is Home -> NavEntry(key) {
                    ContentGreen("Welcome to Nav3") {
                        Button(onClick = {
                            backStack.add(Product("123"))
                        }) {
                            Text("Click to navigate")
                        }
                    }
                }

                is Product -> NavEntry(key) {
                    ContentBlue("Product ${key.id} ")
                }

                else -> NavEntry(Unit) { Text("Unknown route") }
            }
        }
    )
}

ডিফল্ট হিসেবে, NavDisplay ব্যাক স্ট্যাকের সবচেয়ে উপরের NavEntry-কে সিঙ্গেল পেন লেআউটে দেখায়। নিচের রেকর্ডিংয়ে এই অ্যাপ চলতে দেখা যাচ্ছে:

দুটি গন্তব্য সহ `NavDisplay`-এর
ডিফল্ট আচরণ।
ছবি ২. NavDisplayদুটি গন্তব্য সহ ডিফল্ট আচরণ।

ডেস্টিনেশন লাইফসাইকেল

NavDisplay সিন-লেভেল সীমাবদ্ধতা এবং এন্ট্রি-লেভেল সীমাবদ্ধতা, এই দুটির উপর ভিত্তি করে NavEntry-এর লাইফসাইকেল স্টেট সীমিত করতে কাস্টম LifecycleOwners ব্যবহার করে।

Compose-এ লাইফসাইকেল সম্পর্কে আরও জানতে, Jetpack Compose-এ লাইফসাইকেল দেখুন।

সিন-লেভেল লাইফসাইকেল সংক্রান্ত সীমাবদ্ধতা

NavDisplay অ্যাক্টিভ Scene-এর লাইফসাইকেল ম্যানেজ করে। সিন-লেভেল ক্যাপ নিচে উল্লেখ করা পদ্ধতি অনুযায়ী নির্ধারণ করা হয়:

ওভারলে না করা দৃশ্যের জন্য:

  • RESUMED: শুধুমাত্র তখনই অনুমতি দেওয়া হয় যখন সিন ট্রানজিশন সেট হয়ে যায় এবং এর উপরে কোনও অ্যাক্টিভ ওভারলে সিন দেখানো হয় না।
  • STARTED: দৃশ্য ট্রানজিশনের সময় STARTED-এ সীমাবদ্ধ থাকে, যেমন, সামনে বা পিছনে নেভিগেট করার সময় অথবা ওভারলে দিয়ে ঢেকে দেওয়া হলে।

ডায়ালগ বা স্ক্রিনের নিচে অ্যাটাচ করা শিটের মতো ওভারলে করা দৃশ্যের জন্য:

  • RESUMED: শুধুমাত্র সবচেয়ে উপরে থাকা, বর্তমানে অ্যাক্টিভ ওভারলে সিনেই অনুমতি দেওয়া হয়।
  • STARTED: STARTED-এ সীমাবদ্ধ করা হয়েছে, এমন যেকোনও অন্তর্নিহিত ওভারলে দৃশ্যের জন্য যা নতুন ওভারলে দ্বারা কভার করা হয়েছে।

এন্ট্রি-লেভেল লাইফসাইকেল স্টেট

ব্যাক স্ট্যাকে উপস্থিতির উপর ভিত্তি করে লাইব্রেরি প্রতিটি স্বতন্ত্র NavEntry সর্বাধিক লাইফসাইকেল স্টেট ম্যানেজ করে:

  • RESUMED: বর্তমান ব্যাক স্ট্যাকে এন্ট্রি থাকলে, এর লাইফসাইকেল RESUMED পর্যন্ত যেতে পারবে (সিন-লেভেল ক্যাপের সাপেক্ষে)।
  • CREATED: এন্ট্রি ব্যাক স্ট্যাকে আর না থাকলে, যেমন, এটি পপ করা হয়েছে কিন্তু অ্যানিমেট করে সরিয়ে দেওয়ার সময় স্ক্রিনে এখনও রেন্ডার করা হচ্ছে, লাইব্রেরি কঠোরভাবে এর লাইফসাইকেল CREATED-এ সীমাবদ্ধ করে। এই সীমা নিশ্চিত করে যে ব্যাকগ্রাউন্ড বা বেরিয়ে যাওয়া এন্ট্রিগুলি অ্যাক্টিভ কাজ করা বন্ধ করে দেয় যেমন, ফ্লো সংগ্রহ করা বা RESUMED বা STARTED স্টেটের সাথে যুক্ত কোরাউটিন লঞ্চ করা, যখন সেগুলি বেরিয়ে যাওয়ার ট্রানজিশন সম্পূর্ণ করে।

সেগুলি কীভাবে একত্রিত হয়

যেমন, NavEntry-এর চূড়ান্ত লাইফসাইকেল স্ট্যাটাস নিম্নলিখিতভাবে সমাধান করা হয়:

পরিস্থিতি দৃশ্য-লেভেল ক্যাপ এন্ট্রি-লেভেল ক্যাপ কার্যকর ক্যাপ
অ্যাক্টিভ এন্ট্রি, সেটেলড স্ক্রিন (কোনও ট্রানজিশন বা ওভারলে নেই) RESUMED RESUMED RESUMED
ট্রানজিশনের সময় অ্যাক্টিভ এন্ট্রি (নেভিগেট করা হচ্ছে বা নেভিগেট করা হচ্ছে না) STARTED RESUMED STARTED
অ্যাক্টিভ এন্ট্রি, ওভারলে দিয়ে ঢাকা (যেমন, ডায়ালগ খোলা আছে) STARTED RESUMED STARTED
পপ-আপ এন্ট্রি, অ্যানিমেট করে বেরিয়ে যাচ্ছে STARTED বা RESUMED CREATED CREATED

সবগুলি একসাথে রাখা হচ্ছে

নিচের ডায়াগ্রাম থেকে বোঝা যায় যে কীভাবে Navigation 3-এর বিভিন্ন অবজেক্টের মধ্যে ডেটা ফ্লো হয়:

Navigation 3-এর বিভিন্ন অবজেক্টের মধ্যে কীভাবে ডেটা ফ্লো হয় তার ভিজ্যুয়ালাইজেশন।
ছবি ৩. Navigation 3-এ বিভিন্ন অবজেক্টের মাধ্যমে কীভাবে ডেটা ফ্লো হয় তা ডায়াগ্রামে দেখানো হয়েছে।
  1. নেভিগেশন ইভেন্ট পরিবর্তন শুরু করে। ব্যবহারকারীর ইন্টার‍্যাকশনের প্রতিক্রিয়া হিসেবে ব্যাক স্ট্যাক থেকে কী যোগ করা বা সরানো হয়।

  2. ব্যাক স্ট্যাক স্টেটে পরিবর্তন হলে কন্টেন্ট রিট্রিভাল ট্রিগার হয়। NavDisplay (ব্যাক স্ট্যাক রেন্ডার করে এমন কম্পোজ করার উপযুক্ত) ব্যাক স্ট্যাক পর্যবেক্ষণ করে। এর ডিফল্ট কনফিগারেশনে, এটি একটি সিঙ্গেল পেন লেআউটে সবচেয়ে উপরের ব্যাক স্ট্যাক এন্ট্রি দেখায়। ব্যাক স্ট্যাকের সবচেয়ে উপরের কী পরিবর্তন হলে, NavDisplay এন্ট্রি প্রদানকারীর থেকে সংশ্লিষ্ট কন্টেন্টের অনুরোধ করার জন্য এই কী ব্যবহার করে।

  3. এন্ট্রি প্রদানকারী কন্টেন্ট সাপ্লাই করে। এন্ট্রি প্রদানকারী হল এমন একটি ফাংশন যা NavEntry-এর জন্য একটি কী সমাধান করে। NavDisplay-এর থেকে কী পাওয়ার পরে, এন্ট্রি প্রদানকারী সংশ্লিষ্ট NavEntry প্রদান করে, যার মধ্যে কী ও কন্টেন্ট দুটিই থাকে।

  4. কন্টেন্ট দেখানো হয়। NavDisplay NavEntry পায় এবং কন্টেন্ট দেখায়।