Saat menggunakan DSL Kotlin untuk membuat grafik, menjaga tujuan dan dalam satu file mungkin sulit dikelola. Ini adalah terutama jika Anda memiliki banyak fitur independen.
Mengekstrak tujuan
Anda harus memindahkan tujuan ke ekstensi NavGraphBuilder
fungsi-fungsi lainnya. Rute harus dekat dengan rute yang menentukannya, dan
layar yang mereka tampilkan. Misalnya, pertimbangkan kode tingkat aplikasi berikut
yang membuat tujuan yang menampilkan daftar kontak:
// MyApp.kt
@Serializable
object Contacts
@Composable
fun MyApp() {
...
NavHost(navController, startDestination = Contacts) {
composable<Contacts> { ContactsScreen( /* ... */ ) }
}
}
Anda harus memindahkan kode khusus navigasi ke dalam file terpisah:
// ContactsNavigation.kt
@Serializable
object Contacts
fun NavGraphBuilder.contactsDestination() {
composable<Contacts> { ContactsScreen( /* ... */ ) }
}
// MyApp.kt
@Composable
fun MyApp() {
...
NavHost(navController, startDestination = Contacts) {
contactsDestination()
}
}
Definisi rute dan tujuan kini terpisah dari aplikasi utama dan
Anda dapat memperbaruinya secara terpisah. Aplikasi utama hanya
bergantung pada satu
fungsi ekstensi. Dalam hal ini, data itu adalah
NavGraphBuilder.contactsDestination()
.
Fungsi ekstensi NavGraphBuilder
membentuk jembatan antara stateless
fungsi composable tingkat layar dan logika khusus Navigasi. Lapisan ini dapat
juga menentukan asal status dan cara Anda menangani peristiwa.
Contoh
Cuplikan berikut memperkenalkan tujuan baru untuk menampilkan nama kontak detail, dan memperbarui tujuan daftar kontak yang ada untuk menampilkan peristiwa navigasi untuk menampilkan detail kontak.
Berikut adalah kumpulan layar standar yang dapat berupa internal
untuk modulnya sendiri, jadi
modul lain tidak dapat mengaksesnya:
// ContactScreens.kt
// Displays a list of contacts
@Composable
internal fun ContactsScreen(
uiState: ContactsUiState,
onNavigateToContactDetails: (contactId: String) -> Unit
) { ... }
// Displays the details for an individual contact
@Composable
internal fun ContactDetailsScreen(contact: ContactDetails) { ... }
Membuat tujuan
Fungsi ekstensi NavGraphBuilder
berikut membuat tujuan
yang menunjukkan composable ContactsScreen
. Selain itu, ia sekarang menghubungkan
layar dengan ViewModel
yang menyediakan status UI layar dan menangani
logika bisnis terkait layar.
Peristiwa navigasi, seperti navigasi ke tujuan detail kontak,
diekspos ke pemanggil, bukan ditangani oleh ViewModel
.
// ContactsNavigation.kt
@Serializable
object Contacts
// Adds contacts destination to `this` NavGraphBuilder
fun NavGraphBuilder.contactsDestination(
// Navigation events are exposed to the caller to be handled at a higher level
onNavigateToContactDetails: (contactId: String) -> Unit
) {
composable<Contacts> {
// The ViewModel as a screen level state holder produces the screen
// UI state and handles business logic for the ConversationScreen
val viewModel: ContactsViewModel = hiltViewModel()
val uiState = viewModel.uiState.collectAsStateWithLifecycle()
ContactsScreen(
uiState,
onNavigateToContactDetails
)
}
}
Anda dapat menggunakan pendekatan yang sama untuk membuat tujuan yang menampilkan
ContactDetailsScreen
. Dalam hal ini, alih-alih mendapatkan status UI dari
Anda dapat memperolehnya langsung dari NavBackStackEntry
.
// ContactsNavigation.kt
@Serializable
internal data class ContactDetails(val id: String)
fun NavGraphBuilder.contactDetailsScreen() {
composable<ContactDetails> { navBackStackEntry ->
ContactDetailsScreen(contact = navBackStackEntry.toRoute())
}
}
Mengenkapsulasi peristiwa navigasi
Dengan cara yang sama seperti mengenkapsulasi tujuan, Anda dapat melakukan enkapsulasi
peristiwa navigasi untuk menghindari paparan jenis rute yang tidak perlu. Lakukan ini dengan
membuat fungsi ekstensi di NavController
.
// ContactsNavigation.kt
fun NavController.navigateToContactDetails(id: String) {
navigate(route = ContactDetails(id = id))
}
Satukan
Kode navigasi untuk menampilkan kontak kini terpisah dengan rapi dari grafik navigasi aplikasi. Aplikasi harus:
- Panggil fungsi ekstensi
NavGraphBuilder
untuk membuat tujuan - Hubungkan tujuan tersebut dengan memanggil fungsi ekstensi
NavController
untuk peristiwa navigasi
// MyApp.kt
@Composable
fun MyApp() {
...
NavHost(navController, startDestination = Contacts) {
contactsDestination(onNavigateToContactDetails = { contactId ->
navController.navigateToContactDetails(id = contactId)
})
contactDetailsDestination()
}
}
Ringkasan
- Enkapsulasi kode navigasi untuk serangkaian layar terkait dengan menempatkannya dalam file terpisah
- Mengekspos tujuan dengan membuat fungsi ekstensi di
NavGraphBuilder
- Mengekspos peristiwa navigasi dengan membuat fungsi ekstensi di
NavController
- Gunakan
internal
untuk merahasiakan layar dan jenis rute