เมื่อใช้ Kotlin DSL เพื่อสร้างกราฟ โดยเก็บปลายทางและ เหตุการณ์การไปยังส่วนต่างๆ ในไฟล์เดียวอาจทำให้จัดการได้ยาก นี่คือ โดยเฉพาะหากคุณมีฟีเจอร์อิสระหลายรายการ
ดึงข้อมูลปลายทาง
คุณควรย้ายปลายทางไปยังส่วนขยาย NavGraphBuilder
ลูกค้าควรอาศัยอยู่ใกล้กับเส้นทางที่ระบุตนเอง และ
หน้าจอที่แสดง ตัวอย่างเช่น ลองพิจารณาโค้ดระดับแอปต่อไปนี้
ที่สร้างปลายทางซึ่งแสดงรายการรายชื่อติดต่อ ดังนี้
// MyApp.kt
@Serializable
object Contacts
@Composable
fun MyApp() {
...
NavHost(navController, startDestination = Contacts) {
composable<Contacts> { ContactsScreen( /* ... */ ) }
}
}
คุณควรย้ายโค้ดเฉพาะสำหรับการนำทางไปไว้ในไฟล์แยกต่างหาก
// ContactsNavigation.kt
@Serializable
object Contacts
fun NavGraphBuilder.contactsDestination() {
composable<Contacts> { ContactsScreen( /* ... */ ) }
}
// MyApp.kt
@Composable
fun MyApp() {
...
NavHost(navController, startDestination = Contacts) {
contactsDestination()
}
}
คำจำกัดความเส้นทางและจุดหมายนั้นจะแยกออกจากแอปหลักและ
คุณก็สามารถอัปเดตแยกกันได้ แอปหลักจะขึ้นอยู่กับแอปเดียวเท่านั้น
ของส่วนขยาย ในกรณีนี้ จะ
NavGraphBuilder.contactsDestination()
ฟังก์ชันส่วนขยาย NavGraphBuilder
จะสร้างบริดจ์ระหว่างสถานะแบบไม่เก็บสถานะ
ฟังก์ชัน Composable ระดับหน้าจอและตรรกะเฉพาะการนำทาง เลเยอร์นี้สามารถ
จะระบุที่มาของรัฐและวิธีที่คุณจัดการกับเหตุการณ์ด้วย
ตัวอย่าง
ข้อมูลโค้ดต่อไปนี้จะแนะนำปลายทางใหม่เพื่อแสดงข้อมูลติดต่อ รายละเอียด และอัปเดตปลายทางรายการที่อยู่ติดต่อที่มีอยู่ให้ แสดง เหตุการณ์การนำทางเพื่อแสดงรายละเอียดของรายชื่อติดต่อ
ต่อไปนี้เป็นชุดหน้าจอทั่วไปที่สามารถinternal
เป็นโมดูลของตัวเองได้
โมดูลอื่นๆ ไม่สามารถเข้าถึงได้:
// 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) { ... }
สร้างปลายทาง
ฟังก์ชันส่วนขยาย NavGraphBuilder
ต่อไปนี้จะสร้างปลายทาง
ซึ่งแสดง ContactsScreen
Composable นอกจากนี้ ยังเชื่อมต่อ
หน้าจอด้วย ViewModel
ที่ให้สถานะ UI ของหน้าจอและจัดการ
แต่ใช้ตรรกะทางธุรกิจที่
เกี่ยวข้องกับหน้าจอ
เหตุการณ์การนําทาง เช่น การไปยังปลายทางของรายละเอียดการติดต่อนั้น
เห็นแก่ผู้โทรแทนที่จะให้ 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
)
}
}
คุณสามารถใช้วิธีการเดียวกันนี้เพื่อสร้างปลายทางที่แสดง
ContactDetailsScreen
ในกรณีนี้ แทนที่จะได้รับสถานะ UI จาก
ดูโมเดลนี้ได้จาก NavBackStackEntry
โดยตรง
// ContactsNavigation.kt
@Serializable
internal data class ContactDetails(val id: String)
fun NavGraphBuilder.contactDetailsScreen() {
composable<ContactDetails> { navBackStackEntry ->
ContactDetailsScreen(contact = navBackStackEntry.toRoute())
}
}
สรุปเหตุการณ์การนำทาง
เช่นเดียวกับการห่อหุ้มปลายทาง คุณสามารถห่อหุ้มปลายทางได้
เหตุการณ์การนำทางเพื่อหลีกเลี่ยงการเปิดเผยประเภทเส้นทางโดยไม่จำเป็น ดำเนินการโดย
การสร้างฟังก์ชันส่วนขยายใน NavController
// ContactsNavigation.kt
fun NavController.navigateToContactDetails(id: String) {
navigate(route = ContactDetails(id = id))
}
นำมารวมกัน
รหัสการนำทางสำหรับการแสดงผู้ติดต่อถูกแยกออกจาก ของกราฟการนำทางของแอป โดยแอปต้องมีคุณสมบัติต่อไปนี้
- เรียกใช้ฟังก์ชันของส่วนขยาย
NavGraphBuilder
เพื่อสร้างปลายทาง - เชื่อมต่อปลายทางเหล่านั้นโดยเรียกใช้ฟังก์ชันของส่วนขยาย
NavController
สําหรับเหตุการณ์การนําทาง
// MyApp.kt
@Composable
fun MyApp() {
...
NavHost(navController, startDestination = Contacts) {
contactsDestination(onNavigateToContactDetails = { contactId ->
navController.navigateToContactDetails(id = contactId)
})
contactDetailsDestination()
}
}
ข้อมูลสรุป
- ห่อหุ้มรหัสการนำทางสำหรับชุดหน้าจอที่เกี่ยวข้องด้วยการวาง ในไฟล์แยกต่างหาก
- แสดงปลายทางด้วยการสร้างฟังก์ชันส่วนขยายใน
NavGraphBuilder
- แสดงเหตุการณ์การนำทางด้วยการสร้างฟังก์ชันส่วนขยายใน
NavController
- ใช้
internal
เพื่อรักษาหน้าจอและประเภทเส้นทางให้เป็นส่วนตัว