নেভিগেশন স্টেট সেভ ও ম্যানেজ করা

নিম্নলিখিত বিভাগে আপনার ব্যাক স্ট্যাক সেভ করা এবং ব্যাক স্ট্যাকের এন্ট্রি সম্পর্কিত স্টোরিং স্টেট সংক্রান্ত কৌশল বর্ণনা করা হয়েছে।

আপনার ব্যাক স্ট্যাক সেভ করা

কনফিগারেশনে পরিবর্তন ও প্রসেস ডেথ সহ বিভিন্ন লাইফসাইকেল ইভেন্ট জুড়ে আপনার অ্যাপের নেভিগেশন স্টেট বজায় রাখা, ব্যবহারকারীর ভালো অভিজ্ঞতার জন্য অত্যন্ত গুরুত্বপূর্ণ। Navigation 3-এ, আপনার ব্যাক স্ট্যাকের মালিক আপনি, তাই এটি কীভাবে তৈরি বা সেভ করবেন সেই বিষয়ে কোনও কঠোর নির্দেশিকা নেই। তবে, নেভিগেশন ৩ একটি সুবিধাজনক পদ্ধতি অফার করে যা আপনাকে সেভ করা যায় এমন ব্যাক স্ট্যাক প্রদান করে: rememberNavBackStack।

rememberNavBackStack ব্যবহার করুন

rememberNavBackStack কম্পোজেবল ফাংশনটি এমনভাবে ডিজাইন করা হয়েছে যাতে এটি একটি ব্যাক স্ট্যাক তৈরি করতে পারে যা কনফিগারেশন পরিবর্তন এবং প্রসেস বন্ধ হয়ে যাওয়া সত্ত্বেও থেকে যায়।

rememberNavBackStack সঠিকভাবে কাজ করার জন্য, আপনার ব্যাক স্ট্যাকের প্রতিটি কী নির্দিষ্ট প্রয়োজনীয়তা মেনে চলতে হবে:

  • NavKey ইন্টারফেস প্রয়োগ করুন: ব্যাক স্ট্যাকের প্রতিটি কী-তে অবশ্যই NavKey ইন্টারফেস প্রয়োগ করতে হবে। এটি একটি মার্কার ইন্টারফেস হিসেবে কাজ করে যা লাইব্রেরিকে এই সিগন্যাল দেয় যে কী সেভ করা যাবে।
  • @Serializable অ্যানোটেশন থাকতে হবে: NavKey প্রয়োগ করা ছাড়াও, আপনার মূল ক্লাস ও অবজেক্টকে @Serializable অ্যানোটেশন দিয়ে চিহ্নিত করতে হবে।

নিচে দেওয়া স্নিপেটে rememberNavBackStack-এর সঠিক প্রয়োগ দেখানো হয়েছে:

@Serializable
data object Home : NavKey

@Composable
fun NavBackStack() {
    val backStack = rememberNavBackStack(Home)
}

NavKey-এর সাবটাইপ সহ ব্যাক স্ট্যাক মনে রাখা

rememberNavBackStack কম্পোজেবল ফাংশন একটি NavBackStack<NavKey> রিটার্ন করে। আপনার অ্যাপ যদি NavKey-এর নিজস্ব সাবটাইপ নির্ধারণ করে, যেখান থেকে এর সব কী ইনহেরিট করে, তাহলে আপনি কাস্টম remember ফাংশন প্রয়োগ করে সেই টাইপিং বজায় রাখতে পারবেন, যেমনটি নিচে দেখানো হয়েছে:

@Serializable
sealed interface MyAppNavKey : NavKey

@Serializable
data object ScreenA: MyAppNavKey

@Serializable
data class ScreenB(val id: String): MyAppNavKey

@Composable
fun rememberMyAppNavBackStack(vararg elements: MyAppNavKey): NavBackStack<MyAppNavKey> {
    return rememberSerializable(serializer = serializer()) {
        NavBackStack(*elements)
    }
}

@Composable
fun MyApp() {
    // defaultNavBackStack is NavBackStack<NavKey>
    val defaultNavBackStack = rememberNavBackStack(ScreenA)
    // myAppNavBackStack is NavBackStack<MyAppNavKey>
    val myAppNavBackStack = rememberMyAppNavBackStack(ScreenA)
}

খোলা পলিমরফিজম কীভাবে ম্যানেজ করতে হয় সেই বিষয়ে আরও উদাহরণ পেতে— NavBackStackSamples দেখুন।

বিকল্প: ViewModel-এ স্টোর করা

আপনার ব্যাক স্ট্যাক ম্যানেজ করার আরেকটি উপায় হল, এটি ViewModel-এ স্টোর করা। ViewModel বা অন্য কোনও কাস্টম স্টোরেজ ব্যবহার করার সময় প্রসেস বন্ধ হয়ে গেলেও ডেটা যাতে মুছে না যায়, তার জন্য আপনাকে এগুলি করতে হবে:

  • আপনার কী সিরিয়ালাইজ করা যায় কিনা তা নিশ্চিত করুন: rememberNavBackStack-এর মতো, আপনার নেভিগেশন কী সিরিয়ালাইজ করা যায় কিনা তা নিশ্চিত করুন।
  • সিরিয়ালাইজেশন ও ডিসিরিয়ালাইজেশন ম্যানুয়ালি ম্যানেজ করা: আপনার অ্যাপ ব্যাকগ্রাউন্ডে গেলে বা রিস্টোর করার সময়, প্রতিটি কী-এর সিরিয়ালাইজ করা উপস্থাপনা পারসিস্টেন্ট স্টোরেজে (যেমন, SharedPreferences, কোনও ডেটাবেস বা ফাইল) ম্যানুয়ালি সেভ করা এবং সেটি থেকে ডিসিরিয়ালাইজ করার দায়িত্ব আপনার।

ViewModel ইনস্ট্যান্সকে NavEntry অবজেক্টের সাথে স্কোপ করা

কনফিগারেশন পরিবর্তন জুড়ে UI-সম্পর্কিত স্টেট বজায় রাখতে ViewModels ব্যবহার করা হয়, যেমন স্ক্রিন রোটেশন। ডিফল্ট হিসেবে, ViewModels-এর স্কোপ হল নিকটতম ViewModelStoreOwner, যা সাধারণত আপনার Activity বা Fragment হয়।

তবে, আপনি হয়তো পুরো Activity-এর পরিবর্তে ব্যাক স্ট্যাকের কোনও নির্দিষ্ট NavEntry-এ (যেমন, কোনও নির্দিষ্ট স্ক্রিন বা গন্তব্য) ViewModel স্কোপ করতে চাইবেন। এটি নিশ্চিত করে যে ViewModel-এর স্টেট শুধুমাত্র তখনই ধরে রাখা হয় যখন সেই নির্দিষ্ট NavEntry ব্যাক স্ট্যাকের অংশ হয় এবং NavEntry পপ করা হলে তা মুছে ফেলা হয়।

androidx.lifecycle:lifecycle-viewmodel-navigation3 অ্যাড-অন লাইব্রেরি এমন NavEntryDecorator প্রদান করে যা এটিতে সাহায্য করে। এই ডেকোরেটর প্রতিটি NavEntry-এর জন্য ViewModelStoreOwner প্রদান করে। আপনি কোনও NavEntry-এর কন্টেন্টের মধ্যে ViewModel তৈরি করলে (যেমন, কম্পোজে viewModel() ব্যবহার করে), এটি অটোমেটিক ব্যাক স্ট্যাকে সেই নির্দিষ্ট NavEntry-এর কী-এর সাথে স্কোপ করা হয়। এর অর্থ হল, ব্যাক স্ট্যাকে NavEntry যোগ করা হলে ViewModel তৈরি হয় এবং সেটি সরিয়ে দেওয়া হলে মুছে যায়।

ViewModels-এর স্কোপিং NavEntrys-এর জন্য NavEntryDecorator ব্যবহার করতে, এইসব ধাপ অনুসরণ করুন:

  1. আপনার app/build.gradle.kts ফাইলে androidx.lifecycle:lifecycle-viewmodel-navigation3 ডিপেন্ডেন্সি যোগ করুন।
  2. NavDisplay তৈরি করার সময় entryDecorators-এর তালিকায় ডিফল্ট rememberSaveableStateHolderNavEntryDecorator() যোগ করুন।
  3. entryDecorators-এর তালিকায় rememberViewModelStoreNavEntryDecorator() যোগ করুন।

NavDisplay(
    entryDecorators = listOf(
        // Add the default decorators for managing scenes and saving state
        rememberSaveableStateHolderNavEntryDecorator(),
        // Then add the view model store decorator
        rememberViewModelStoreNavEntryDecorator()
    ),
    backStack = backStack,
    entryProvider = entryProvider { },
)