বুঝুন এবং বেসিক বাস্তবায়ন

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

মডেলিং নেভিগেশন অবস্থা

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

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

একটি ব্যাক স্ট্যাক তৈরি করুন

ন্যাভিগেশন ৩-এ, ব্যাক স্ট্যাকে আসলে কোনো কন্টেন্ট থাকে না। এর পরিবর্তে, এতে কন্টেন্টের রেফারেন্স থাকে, যা 'কী' (key) নামে পরিচিত। কী যেকোনো ধরনের হতে পারে, তবে সাধারণত এগুলো সরল, সিরিয়ালাইজেবল ডেটা ক্লাস হয়ে থাকে। কন্টেন্টের পরিবর্তে রেফারেন্স ব্যবহার করার নিম্নলিখিত সুবিধাগুলো রয়েছে:

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

নেভিগেশন ৩ এপিআই-এর একটি মূল ধারণা হলো ব্যাক স্ট্যাকের মালিক আপনি। লাইব্রেরিটি:

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

নিম্নলিখিত উদাহরণটি দেখায় কিভাবে কী (key) এবং একটি ব্যাক স্ট্যাক (back stack) তৈরি করতে হয়, এবং ব্যবহারকারীর নেভিগেশন ইভেন্টের প্রতিক্রিয়ায় ব্যাক স্ট্যাকটি পরিবর্তন করতে হয়:

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

বিষয়বস্তুর চাবিগুলি সমাধান করুন

Navigation 3-এ কন্টেন্টকে NavEntry ব্যবহার করে মডেল করা হয়, যা একটি কম্পোজেবল ফাংশন ধারণকারী একটি ক্লাস। এটি একটি গন্তব্যকে প্রতিনিধিত্ব করে – অর্থাৎ কন্টেন্টের একটি একক অংশ, যেখানে ব্যবহারকারী সামনে এবং পিছনে নেভিগেট করতে পারে।

একটি NavEntry মেটাডেটাও থাকতে পারে – অর্থাৎ এর বিষয়বস্তু সম্পর্কিত তথ্য। এই মেটাডেটা কন্টেইনার অবজেক্ট, যেমন NavDisplay , পড়তে পারে, যা তাদের NavEntry এর বিষয়বস্তু কীভাবে প্রদর্শন করা হবে সে বিষয়ে সিদ্ধান্ত নিতে সাহায্য করে। উদাহরণস্বরূপ, একটি নির্দিষ্ট 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 ডিএসএল ব্যবহার করুন

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-তে নতুন ব্যাক স্ট্যাকের অবস্থা প্রতিফলিত হওয়া উচিত। নেভিগেশন ৩-এ, একটি 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 Scene- স্তরের সীমাবদ্ধতা এবং Entry-স্তরের সীমাবদ্ধতা উভয়ের উপর ভিত্তি করে একটি NavEntry এর লাইফসাইকেল অবস্থা সীমিত করতে কাস্টম LifecycleOwner ব্যবহার করে।

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

দৃশ্য-স্তরের জীবনচক্রের সীমাবদ্ধতা

NavDisplay সক্রিয় Scene গুলোর জীবনচক্র পরিচালনা করে। 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

সবকিছু একসাথে মিলিয়ে

নিম্নলিখিত ডায়াগ্রামটি দেখায় যে নেভিগেশন ৩-এ বিভিন্ন অবজেক্টের মধ্যে কীভাবে ডেটা প্রবাহিত হয়:

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

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

  3. এন্ট্রি প্রোভাইডার কন্টেন্ট সরবরাহ করে । এন্ট্রি প্রোভাইডার হলো এমন একটি ফাংশন যা একটি কী-কে একটি NavEntry তে রূপান্তর করে। NavDisplay থেকে একটি কী গ্রহণ করার পর, এন্ট্রি প্রোভাইডার সংশ্লিষ্ট NavEntry প্রদান করে, যেটিতে কী এবং কন্টেন্ট উভয়ই থাকে।

  4. বিষয়বস্তু প্রদর্শিত হয়NavDisplay NavEntry গ্রহণ করে এবং বিষয়বস্তু প্রদর্শন করে।