Panduan ini menguraikan proses penggantian rute berbasis string dengan jenis Kotlin yang dapat diserialisasi untuk mencapai keamanan waktu kompilasi dan menghilangkan error runtime yang disebabkan oleh salah ketik atau jenis argumen yang salah.
Prasyarat
Sebelum memulai migrasi, pastikan project Anda memenuhi persyaratan berikut:
- Versi Navigation: Update ke Jetpack Navigation 2.8.0 atau yang lebih baru
- Plugin serialisasi Kotlin:
- Tambahkan plugin ke
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" }
- Tambahkan dependensi ke
build.gradle.ktstingkat teratas danbuild.gradle.ktstingkat modul.
Langkah 1: Tentukan Tujuan Anda
Ganti string rute konstanta Anda dengan objek dan class @Serializable.
- Untuk layar tanpa argumen: Gunakan
data object - Untuk layar dengan argumen: Gunakan
data class
Sebelum (berbasis string):
const val ROUTE_HOME = "home"
const val ROUTE_PROFILE = "profile/{userId}"
Setelah (aman menurut jenis):
import kotlinx.serialization.Serializable
@Serializable
object Home
@Serializable
data class Profile(val userId: String)
Langkah 2: Perbarui Konfigurasi NavHost
Perbarui NavHost untuk menggunakan jenis generik baru dalam fungsi composable dan dialog.
Sebelum:
NavHost(navController, startDestination = "home") {
composable("home") { HomeScreen(...) }
composable("profile/{userId}") { backStackEntry ->
val userId = backStackEntry.arguments?.getString("userId")
ProfileScreen(userId)
}
}
Sesudah:
NavHost(navController, startDestination = Home) {
composable<Home> {
HomeScreen(...)
}
composable<Profile> { backStackEntry ->
// The library automatically handles argument extraction
val profile: Profile = backStackEntry.toRoute()
ProfileScreen(profile.userId)
}
}
Langkah 3: Terapkan Panggilan Navigasi yang Aman untuk Jenis
Ganti panggilan navigasi yang diinterpolasi string dengan instance class.
Sebelum:
navController.navigate("profile/user123")
Sesudah:
navController.navigate(Profile(userId = "user123"))
Langkah 4: Mengakses Argumen di ViewModel
Jika menggunakan ViewModel, Anda kini dapat mengekstrak objek rute langsung dari
SavedStateHandle.
Penerapan:
class ProfileViewModel(
savedStateHandle: SavedStateHandle
) : ViewModel() {
// Automatically parses arguments into the Profile class
private val profile = savedStateHandle.toRoute<Profile>()
val userId = profile.userId
}
Langkah 5: (Lanjutan) Menangani Jenis Kustom
Jika perlu meneruskan class data yang kompleks (bukan hanya primitif), Anda harus menentukan
NavType kustom.
- Buat Jenis Kustom:
```kotlin
val SearchFilterType = object : NavType
(isNullableAllowed = false) { override fun get(bundle: Bundle, key: String): SearchFilter? = Json.decodeFromString(bundle.getString(key) ?: return 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)
) { ... }
Praktik terbaik dan tips
- Hierarki Tertutup: Untuk aplikasi besar, kelompokkan rute Anda menggunakan antarmuka atau class tertutup agar struktur navigasi tetap teratur
- Instance Objek: Untuk rute tanpa parameter, selalu gunakan
objectdaripadaclassuntuk menghindari alokasi yang tidak perlu - Jenis Nullable: API baru mendukung jenis nullable (misalnya,
data class Search(val query: String?)) dan menyediakan nilai default secara otomatis - Pengujian: Gunakan
navController.currentBackStackEntry?.hasRoute<T>()untuk memeriksa tujuan saat ini dengan cara yang aman untuk jenis selama pengujian UI