ה-NavController מכיל "מקבץ פעילויות קודמות (back stack)" שכולל את היעדים שהמשתמש ביקר בהם. בזמן שהמשתמש עובר בין המסכים באפליקציה, NavController מוסיף ומסיר יעדים מסטאק החזרה.
במבנה של מחסנית, מקבץ פעילויות קודמות (back stack) הוא מבנה נתונים מסוג 'אחרון שנכנס, ראשון שיוצא'. לכן, הפעולה
NavController דוחפת פריטים לראש המחסנית ומוציאה פריטים מהראש שלה.
התנהגות בסיסית
אלה העובדות העיקריות שכדאי להביא בחשבון לגבי ההתנהגות של ה-backstack:
- היעד הראשון: כשמשתמש פותח את האפליקציה,
NavControllerהפעולה מעבירה את היעד הראשון לראש מקבץ הפעילויות הקודמות (back stack). - הוספה למחסנית: כל שיחה
NavController.navigate()מוסיפה את היעד שצוין לראש המחסנית. - יעד קופץ עליון: הקשה על Up או על Back מפעילה את השיטות
NavController.navigateUp()ו-NavController.popBackStack()בהתאמה. הם מוציאים את היעד העליון מהמחסנית. מידע נוסף על ההבדל בין Up (למעלה) לבין Back (חזרה) זמין בדף עקרונות הניווט.
פתיחה בחלון חדש
השיטה NavController.popBackStack() מנסה להוציא את היעד הנוכחי ממחסנית הגיבוי ולנווט אל היעד הקודם. הפעולה הזו מחזירה את המשתמש צעד אחד אחורה בהיסטוריית הניווט שלו. הפונקציה מחזירה ערך בוליאני שמציין אם הפעולה הצליחה.
חזרה ליעד מסוים
אפשר גם להשתמש ב-popBackStack() כדי לנווט ליעד מסוים. כדי לעשות זאת, צריך להשתמש באחת מההעמסות שלה. יש כמה מאפיינים שמאפשרים להעביר מזהה, כמו מספר שלם id או מחרוזת route. העומסים האלה מעבירים את המשתמש ליעד שמשויך למזהה הנתון. חשוב לציין שהם מוציאים מהמחסנית את כל מה שמעל היעד הזה.
גם העומסים האלה מקבלים inclusive ערך בוליאני. ההגדרה הזו קובעת אם הרכיב
NavController צריך גם להוציא את היעד שצוין ממקבץ הפעילויות הקודמות (back stack) אחרי הניווט אליו.
לדוגמה, קטע הקוד הקצר הזה:
navController.popBackStack(R.id.destinationId, true)
כאן NavController חוזר ליעד עם מזהה המספר השלם destinationId. מכיוון שהערך של הארגומנט inclusive הוא true, הפונקציה
NavController גם מוציאה את היעד שצוין ממקבץ הפעילויות הקודמות (back stack).
טיפול בהחזרה קופצת שנכשלה
כש-popBackStack() מחזירה false, קריאה עוקבת ל-NavController.getCurrentDestination() מחזירה null. המשמעות היא שהאפליקציה הוציאה את היעד האחרון ממקבץ הפעילויות הקודמות (back stack). במקרה כזה, המשתמש רואה רק מסך ריק.
מצב כזה יכול לקרות במקרים הבאים:
- הפונקציה
popBackStack()לא הוציאה שום דבר מהמחסנית. -
popBackStack()הוציא יעד ממקבץ הפעילויות הקודמות (back stack), ועכשיו המקבץ ריק.
כדי לפתור את הבעיה, צריך לעבור ליעד חדש או להתקשר אל finish()
בפעילות כדי לסיים אותה. בקטע הקוד הבא אפשר לראות דוגמה:
kotlin
...
if (!navController.popBackStack()) {
// Call finish() on your Activity
finish()
}
java
...
if (!navController.popBackStack()) {
// Call finish() on your Activity
finish();
}
הגעה ליעד
כדי להסיר יעדים ממקבץ פעילויות קודמות (back stack) כשעוברים מיעד אחד ליעד אחר, מוסיפים ארגומנט popUpTo() לקריאה המשויכת לפונקציה navigate(). popUpTo() instructs the Navigation library to remove some destinations
from the back stack as part of the call to navigate(). ערך הפרמטר הוא המזהה של יעד במקבץ פעילויות קודמות (back stack). המזהה יכול להיות מספר שלם id או מחרוזת route.
אפשר לכלול ארגומנט לפרמטר inclusive עם ערך של true כדי לציין שהיעד שציינתם ב-popUpTo() צריך גם לצאת ממקבץ הפעילויות הקודמות (back stack).
כדי להטמיע את התכונה הזו באופן פרוגרמטי, מעבירים את הערך popUpTo() אל navigate() כחלק מ-NavOptions עם הערך inclusive שמוגדר ל-true. האפשרות הזו פועלת גם במצב כתיבה וגם בתצוגות.
שמירת המצב כשמופיע חלון קופץ
כשמשתמשים ב-popUpTo כדי לנווט ליעד, אפשר לשמור את מקבץ הפעילויות הקודמות ואת המצבים של כל היעדים שהוצאו ממקבץ הפעילויות הקודמות. אחר כך תוכלו לשחזר את מקבץ הפעילויות הקודמות (back stack) ואת היעדים כשמנווטים ליעד הזה במועד מאוחר יותר. כך אפשר לשמור את המצב של יעד מסוים וליצור כמה מחסניות של היסטוריית חזרה.
כדי לעשות זאת באופן פרוגרמטי, מציינים saveState = true כשמוסיפים את popUpTo לאפשרויות הניווט.
אפשר גם לציין את restoreState = true באפשרויות הניווט כדי לשחזר באופן אוטומטי את מקבץ הפעילויות הקודמות (back stack) ואת המצב שמשויך ליעד.
לדוגמה:
navController.navigate(
route = route,
navOptions = navOptions {
popUpTo<A>{ saveState = true }
restoreState = true
}
)
כדי להפעיל שמירה ושחזור של מצב ב-XML, מגדירים את popUpToSaveState כ-true
ואת restoreState כ-true בהתאמה ב-action המשויך.
דוגמה לשימוש
דוגמה מלאה לאותו דבר ב-Compose:
@Composable
fun MyAppNavHost(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController(),
startDestination: Any = A
) {
NavHost(
modifier = modifier,
navController = navController,
startDestination = startDestination
) {
composable<A> {
DestinationA(
onNavigateToB = {
// Pop everything up to, and including, the A destination off
// the back stack, saving the back stack and the state of its
// destinations.
// Then restore any previous back stack state associated with
// the B destination.
// Finally navigate to the B destination.
navController.navigate(route = B) {
popUpTo<A> {
inclusive = true
saveState = true
}
restoreState = true
}
},
)
}
composable<B> { DestinationB(/* ... */) }
}
}
@Composable
fun DestinationA(onNavigateToB: () -> Unit) {
Button(onClick = onNavigateToB) {
Text("Go to A")
}
}
בצורה מפורטת יותר, אתם יכולים לשנות את האופן שבו אתם מתקשרים באמצעות NavController.navigate() בדרכים הבאות:
// Pop everything up to the destination_a destination off the back stack before
// navigating to the "destination_b" destination
navController.navigate("destination_b") {
popUpTo("destination_a")
}
// Pop everything up to and including the "destination_a" destination off
// the back stack before navigating to the "destination_b" destination
navController.navigate("destination_b") {
popUpTo("destination_a") { inclusive = true }
}
// Navigate to the "search” destination only if we’re not already on
// the "search" destination, avoiding multiple copies on the top of the
// back stack
navController.navigate("search") {
launchSingleTop = true
}
מידע כללי על העברת אפשרויות אל NavController.navigate() זמין במדריך לניווט עם אפשרויות.
דוגמה בפורמט XML
דוגמה לשימוש ב-popUpTo ב-XML, באמצעות פעולה:
<action
android:id="@+id/action_a_to_b"
app:destination="@id/b"
app:popUpTo="@+id/a"
app:popUpToInclusive="true"
app:restoreState=”true”
app:popUpToSaveState="true"/>
הצגת חלון קופץ באמצעות פעולות
כשמנווטים באמצעות פעולה, אפשר להוציא יעדים נוספים ממקבץ פעילויות קודמות (back stack). לדוגמה, אם באפליקציה שלכם יש תהליך התחברות ראשוני, אחרי שמשתמש מתחבר, צריך להסיר את כל היעדים שקשורים להתחברות ממקבץ הפעילויות הקודמות (back stack), כדי שהכפתור "הקודם" לא יחזיר את המשתמשים לתהליך ההתחברות.
קריאה נוספת
מידע נוסף זמין בדפים הבאים:
- ניווט מעגלי: במקרים שבהם זרימות הניווט הן מעגליות, כדאי לדעת איך אפשר להימנע ממצב שבו מחסנית החזרה מלאה מדי.
- יעדים של תיבות דו-שיח: במאמר הזה מוסבר איך היעדים של תיבות דו-שיח משפיעים על ניהול מקבץ הפעילויות הקודמות (back stack).