Navigation 3-এ মাইগ্রেট করা

নেভিগেশন ৩, Jetpack Compose কীভাবে নেভিগেশন স্টেট ম্যানেজ করে সেটির মধ্যে একটি মৌলিক পরিবর্তনকে উপস্থাপন করে এবং নেভিগেশন ২-এর তুলনায় উল্লেখযোগ্য আর্কিটেকচারাল সুবিধা প্রদান করে।

Wear Compose অ্যাপকে নেভিগেশন ২ থেকে নেভিগেশন ৩-এ মাইগ্রেট করার জন্য প্রয়োজনীয় আর্কিটেকচারাল পরিবর্তন ও ধাপগুলি সম্পর্কে জানুন।

Navigation 3-এর প্রধান সুবিধা

  • সরাসরি ব্যাক স্ট্যাক কন্ট্রোল: NavBackStack হল মূলত NavKey অবজেক্টের একটি পরিবর্তনযোগ্য তালিকা, যা ব্যবহারকারীর দেখা স্ক্রিনের ইতিহাসকে উপস্থাপন করে। আপনি ঠিক সেইভাবেই এটি কন্ট্রোল করেন যেভাবে কোনও Kotlin MutableList (add, removeLast, clear) কন্ট্রোল করেন। নেভিগেশন অ্যাকশন পারফর্ম করতে আপনি সরাসরি লিস্ট ম্যানিপুলেট করেন, যেমন, এগিয়ে যাওয়ার জন্য একটি কী যোগ করা অথবা পিছিয়ে যাওয়ার জন্য একটি কী সরানো।
  • কম্পোজ-ফার্স্ট ডিজাইন: ব্যাক স্ট্যাককে স্ট্যান্ডার্ড অবজার্ভেবল স্টেট হিসেবে মডেল করা হয়। আপনার নেভিগেশন ইতিহাস পরিবর্তন করা ঠিক অন্য কোনও কম্পোজ স্টেটের মতো আচরণ করে, বর্তমান স্ক্রিন দেখানোর জন্য অটোমেটিক রিকম্পোজিশন ট্রিগার করে।
  • ডিফল্ট হিসেবে টাইপ-সেফ: স্ট্রিং-ভিত্তিক রুট সম্পূর্ণভাবে সরিয়ে দেওয়া হয়েছে। নেভিগেশন, সিরিয়ালাইজ করা যায় এমন ডেটা অবজেক্ট ও ডেটা ক্লাস ব্যবহার করে।
  • ডিকাপেলড প্রেজেন্টেশন (সিন স্ট্র্যাটেজি): UI ট্রানজিশন লেয়ার (NavDisplay ও SwipeDismissableSceneStrategy) সম্পূর্ণভাবে স্টেট ট্র্যাকিং (NavBackStack) থেকে আলাদা করা হয়েছে, এর ফলে বিল্ট-ইন Wear OS নেভিগেশন ট্রানজিশন আরও সহজে ইন্টিগ্রেট করা যায়।

মাইগ্রেশনের ধাপ

১. ডিপেন্ডেন্সি আপডেট করা

পুরনো androidx.wear.compose:compose-navigation ডিপেন্ডেন্সি সরিয়ে দিন এবং নতুন স্প্লিট নেভিগেশন ৩ ডিপেন্ডেন্সি যোগ করুন, এর সাথে কোটলিন সিরিয়ালাইজেশন সাপোর্টও যোগ করুন।

সরিয়ে দিন:

implementation("androidx.wear.compose:compose-navigation:...")

যোগ করুন:

implementation("androidx.navigation3:navigation3-runtime:...") // State logic
implementation("androidx.navigation3:navigation3-ui:...")      // Display logic
implementation("androidx.wear.compose:compose-navigation3:...") // Wear gestures
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:...") // Requires compiler plugin

২. NavKey প্রয়োগ করতে গন্তব্য আপডেট করুন

নেভিগেশন ২-এ, আপনি হয়ত রাউটিংয়ের জন্য স্ট্রিং বা জেনেরিক অবজেক্ট ব্যবহার করেছেন। নেভিগেশন ৩-এ, আপনাকে অবশ্যই NavKey মার্কার ইন্টারফেস প্রয়োগ করতে হবে এবং @Serializable দিয়ে প্রতিটি স্ক্রিন অবজেক্টকে অ্যানোটেট করতে হবে।

এটির প্রয়োজন কেন? যাতে ব্যাক স্ট্যাক সেভ করা যায় এবং প্রসেস বন্ধ হয়ে গেলেও রিস্টোর করা যায়, তার জন্য অন্তর্নিহিত navigation3-runtime স্টেট সিরিয়ালাইজ করার জন্য kotlinx-serialization-এর উপর নির্ভর করে।

আগে (নেভিগেশন ২ - জেনেরিক টাইপ-সেফ রুট):

sealed class Nav2Screen {
    data object Landing : Nav2Screen()
    data object List : Nav2Screen()
}

পরে (নেভিগেশন ৩ - NavKey + Serializable):

@Serializable
sealed interface MigrationScreen : NavKey {
    @Serializable
    data object Landing : MigrationScreen

    @Serializable
    data object List : MigrationScreen
}

৩. রাউটিং লজিক (NavController থেকে NavBackStack) পরিবর্তন করুন

rememberNavBackStack ব্যবহার করে ইনিশিয়ালাইজ করা NavBackStack দিয়ে আপনার NavController পরিবর্তন করুন। এছাড়াও, আপনাকে Wear OS-এর জন্য নির্দিষ্টভাবে SwipeDismissableSceneStrategy ইনস্ট্যানশিয়েট করতে হবে।

আগে (নেভিগেশন ২):

val navController = rememberSwipeDismissableNavController()

পরে (নেভিগেশন ৩):

val backStack = rememberNavBackStack(MigrationScreen.Landing as NavKey)
val strategy = rememberSwipeDismissableSceneStrategy<NavKey>()

৪. NavHost-এর জায়গায় NavDisplay এবং entryProvider DSL ব্যবহার করুন

NavHost কন্টেনার ও এর ইন্টার্নাল composable("route") { ... } বিল্ডার DSL-এর পরিবর্তে NavDisplay ও entryProvider { entry<Key> { ... } } DSL ব্যবহার করা হয়।

আগে (নেভিগেশন ২):

SwipeDismissableNavHost(navController = navController, startDestination = "menu") {
    composable("menu") {
        GreetingScreen(
            onShowList = { navController.navigate("list") }
        )
    }
    composable("list") {
        ListScreen()
    }
}

পরে (নেভিগেশন ৩):

NavDisplay(
    backStack = backStack,
    sceneStrategies = listOf(strategy),
    entryProvider = entryProvider {
        entry<MigrationScreen.Landing> {
            GreetingScreen(
                onShowList = { backStack.add(MigrationScreen.List) }
            )
        }
        entry<MigrationScreen.List> {
            ListScreen()
        }
    }
)