כשמשתמשים ב-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
כדי לשמור על הפרטיות של המסכים וסוגי המסלולים