Panduan: Bermigrasi ke Navigasi Keamanan Jenis di Compose dan Navigation 2

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:

  1. Versi Navigation: Update ke Jetpack Navigation 2.8.0 atau yang lebih baru
  2. Plugin serialisasi Kotlin:
  3. 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.kts tingkat teratas dan build.gradle.kts tingkat 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.

  1. 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 object daripada class untuk 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