ה-NavController מכיל "מקבץ פעילויות קודמות (back stack)" שכולל את היעדים שהמשתמש ביקר בהם. בזמן שהמשתמש מנווט בין המסכים באפליקציה, הספרייה
NavController מוסיפה ומסירה יעדים ממקבץ פעילויות קודמות (back stack).
מקבץ פעילויות קודמות (back stack) הוא מבנה נתונים מסוג 'אחרון שנכנס, ראשון שיוצא'. לכן, הפעולה NavController דוחפת פריטים לראש המחסנית ושולפת פריטים מראש המחסנית.
התנהגות בסיסית
אלה העובדות העיקריות שכדאי להביא בחשבון לגבי ההתנהגות של ה-backstack:
- יעד ראשון: כשהמשתמש פותח את האפליקציה,
NavControllerהיעד הראשון מועבר לראש מקבץ הפעילויות הקודמות (back stack). - הוספה למחסנית: כל שיחה
NavController.navigate()מוסיפה את היעד שצוין לראש המחסנית. - יעד קופץ מוביל: הקשה על Up או על Back מפעילה את השיטות
NavController.navigateUp()ו-NavController.popBackStack()בהתאמה. הם מוציאים את היעד העליון מהמחסנית. מידע נוסף על ההבדל בין Up (למעלה) לבין Back (חזרה) זמין בדף עקרונות הניווט.
פתיחה בחלון חדש
השיטה NavController.popBackStack() מנסה להוציא את היעד הנוכחי ממקבץ הפעילויות הקודמות (back stack) ולנווט אל היעד הקודם. הפעולה הזו מחזירה את המשתמש צעד אחד אחורה בהיסטוריית הניווט שלו. הפונקציה מחזירה ערך בוליאני שמציין אם הפעולה הצליחה.
חזרה ליעד מסוים
אפשר גם להשתמש בלחצן 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 המשויך.
דוגמה בפורמט 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"/>
דוגמה לכתיבה
דוגמה מלאה לאותו דבר ב-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() זמין במדריך לניווט עם אפשרויות.
הצגת חלון קופץ באמצעות פעולות
כשמנווטים באמצעות פעולה, אפשר להוציא יעדים נוספים ממקבץ פעילויות קודמות (back stack). לדוגמה, אם לאפליקציה שלכם יש תהליך התחברות ראשוני, אחרי שמשתמש מתחבר, צריך להסיר את כל היעדים שקשורים להתחברות ממקבץ הפעילויות הקודמות (back stack), כדי שהכפתור "הקודם" לא יחזיר את המשתמשים לתהליך ההתחברות.
מקורות מידע נוספים
מידע נוסף זמין בדפים הבאים:
- ניווט מעגלי: במקרים שבהם זרימות הניווט הן מעגליות, כדאי לדעת איך אפשר להימנע ממצב שבו מחסנית החזרה מלאה מדי.
- יעדים של תיבות דו-שיח: במאמר הזה מוסבר איך היעדים של תיבות דו-שיח משפיעים על ניהול מקבץ הפעילויות הקודמות (back stack).