ห่อหุ้มรหัสการนำทาง

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