השלמת קוד הניווט

כשמשתמשים ב-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 יוצרת את הגבול בין רשת ללא שמירת מצב פונקציה קומפוזבילית ברמת המסך ולוגיקה ספציפית לניווט. השכבה הזאת יכולה מגדירים גם מאיפה מגיעה המדינה ואיך מטפלים באירועים.

דוגמה

קטע הקוד הבא מציג יעד חדש להצגת פרטים של איש קשר ומעדכן את היעד הקיים של רשימת אנשי הקשר כדי לחשוף אירוע ניווט כדי להציג את פרטי איש הקשר.

זו קבוצה אופיינית של מסכים שיכולים להיות 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. בנוסף, עכשיו הוא מתחבר במסך עם ViewModel שמספק את המצב של ממשק המשתמש של המסך ומטפל לוגיקה עסקית שקשורה למסך.

אירועי ניווט, כמו ניווט ליעד של הפרטים ליצירת קשר, נחשפו למתקשר/ת ולא מטופל על ידי 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 במקרה כזה, במקום לקבל את מצב ממשק המשתמש את המודל לצפייה, אפשר לקבל אותו ישירות מ-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( contactId ->
        navController.navigateToContactDetails(id = contactId)
     })
     contactDetailsDestination()
  }
}

לסיכום

  • להקיף את קוד הניווט עבור קבוצה קשורה של מסכים על ידי הצבתו בקובץ נפרד
  • חושפים יעדים על ידי יצירת פונקציות של תוספים ב-NavGraphBuilder
  • חשיפה של אירועי ניווט על ידי יצירת פונקציות של תוספים ב-NavController
  • שימוש ב-internal כדי לשמור על הפרטיות של המסכים וסוגי המסלולים