গাইড: কম্পোজ এবং নেভিগেশন ২-এ টাইপ-সেফ নেভিগেশনে স্থানান্তরিত করা

এই নির্দেশিকাটি স্ট্রিং-ভিত্তিক রুটগুলিকে সিরিয়ালাইজেবল কোটলিন টাইপ দিয়ে প্রতিস্থাপনের প্রক্রিয়ার রূপরেখা দেয় যাতে কম্পাইল-টাইম নিরাপত্তা অর্জন করা যায় এবং টাইপো বা ভুল আর্গুমেন্ট টাইপের কারণে রানটাইম ক্র্যাশ দূর করা যায়।

পূর্বশর্ত

মাইগ্রেশন শুরু করার আগে, যাচাই করুন যে আপনার প্রকল্পটি নিম্নলিখিত প্রয়োজনীয়তাগুলি পূরণ করে:

  1. নেভিগেশন সংস্করণ : জেটপ্যাক নেভিগেশন 2.8.0 বা উচ্চতর সংস্করণে আপডেট করুন
  2. কোটলিন সিরিয়ালাইজেশন প্লাগইন :
  3. libs.versions.toml এ প্লাগইনটি যোগ করুন:
[libraries]
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }

[plugins]
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
  • আপনার শীর্ষ-স্তরের build.gradle.kts এবং module-level build.gradle.kts এ নির্ভরতা যোগ করুন।

ধাপ ১: আপনার গন্তব্যস্থল নির্ধারণ করুন

আপনার ধ্রুবক রুট স্ট্রিংগুলিকে @Serializable অবজেক্ট এবং ক্লাস দিয়ে প্রতিস্থাপন করুন।

  • আর্গুমেন্ট ছাড়া স্ক্রিনের জন্য : একটি data object ব্যবহার করুন
  • আর্গুমেন্ট সহ স্ক্রিনের জন্য : একটি data class ব্যবহার করুন

আগে (স্ট্রিং ভিত্তিক):

const val ROUTE_HOME = "home"
const val ROUTE_PROFILE = "profile/{userId}"

পরে (নিরাপদ টাইপ করুন):

import kotlinx.serialization.Serializable

@Serializable
object Home

@Serializable
data class Profile(val userId: String)

ধাপ ২: NavHost কনফিগারেশন আপডেট করুন

composable এবং dialog ফাংশনে নতুন জেনেরিক টাইপ ব্যবহার করতে আপনার NavHost আপডেট করুন।

আগে:

NavHost(navController, startDestination = "home") {
    composable("home") { HomeScreen(...) }
    composable("profile/{userId}") { backStackEntry ->
        val userId = backStackEntry.arguments?.getString("userId")
        ProfileScreen(userId)
    }
}

পরে:

NavHost(navController, startDestination = Home) {
    composable<Home> {
        HomeScreen(...)
    }
    composable<Profile> { backStackEntry ->
        // The library automatically handles argument extraction
        val profile: Profile = backStackEntry.toRoute()
        ProfileScreen(profile.userId)
    }
}

ধাপ ৩: টাইপ-সেফ নেভিগেশন কল বাস্তবায়ন করুন

স্ট্রিং-ইন্টারপোলেটেড নেভিগেশন কলগুলিকে ক্লাস ইনস্ট্যান্স দিয়ে প্রতিস্থাপন করুন।

আগে:

navController.navigate("profile/user123")

পরে:

navController.navigate(Profile(userId = "user123"))

ধাপ ৪: ভিউমডেলে আর্গুমেন্ট অ্যাক্সেস করা

যদি আপনি ViewModel ব্যবহার করেন, তাহলে আপনি এখন SavedStateHandle থেকে সরাসরি রুট অবজেক্টটি বের করতে পারবেন।

বাস্তবায়ন:

class ProfileViewModel(
    savedStateHandle: SavedStateHandle
) : ViewModel() {
    // Automatically parses arguments into the Profile class
    private val profile = savedStateHandle.toRoute<Profile>()
    val userId = profile.userId
}

ধাপ ৫: (উন্নত) কাস্টম প্রকারগুলি পরিচালনা করা

যদি আপনার জটিল ডেটা ক্লাস (শুধুমাত্র আদিম নয়) পাস করার প্রয়োজন হয়, তাহলে আপনাকে একটি কাস্টম NavType সংজ্ঞায়িত করতে হবে।

  1. কাস্টম টাইপ তৈরি করুন : ```kotlin val SearchFilterType = object : NavType (isNullableAllowed = false) { override fun get(bundle: Bundle, key: String): SearchFilter? = Json.decodeFromString(bundle.getString(key) ?: null ফেরত দিন)
override fun parseValue(value: String): SearchFilter =
    Json.decodeFromString(Uri.decode(value))

override fun put(bundle: Bundle, key: String, value: SearchFilter) {
    bundle.putString(key, Json.encodeToString(value))
}

}



2. **Register it in the Graph**:
```kotlin
composable<Search>(
    typeMap = mapOf(typeOf<SearchFilter>() to SearchFilterType)
) { ... }

সেরা অনুশীলন এবং টিপস

  • সিল করা শ্রেণিবিন্যাস : বড় অ্যাপের জন্য, নেভিগেশন কাঠামো সুসংগঠিত রাখতে সিল করা ইন্টারফেস বা ক্লাস ব্যবহার করে আপনার রুটগুলিকে গোষ্ঠীভুক্ত করুন।
  • অবজেক্ট ইনস্ট্যান্স : প্যারামিটার ছাড়া রুটের জন্য, অপ্রয়োজনীয় বরাদ্দ এড়াতে সর্বদা class পরিবর্তে object ব্যবহার করুন।
  • Nullable Types : নতুন API nullable Types (উদাহরণস্বরূপ, data class Search(val query: String?) ) সমর্থন করে এবং স্বয়ংক্রিয়ভাবে ডিফল্ট মান প্রদান করে।
  • পরীক্ষা : UI পরীক্ষার সময় টাইপ-সেফ পদ্ধতিতে বর্তমান গন্তব্য পরীক্ষা করতে navController.currentBackStackEntry?.hasRoute<T>() ব্যবহার করুন।