เมื่อใช้ 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เพื่อรักษาหน้าจอและประเภทเส้นทางให้เป็นส่วนตัว