يحتوي NavController على "مجموعة من الوجهات السابقة" تتضمّن الوجهات التي زارها المستخدِم. أثناء انتقال المستخدِم إلى شاشات مختلفة في تطبيقك، يضيف NavController الوجهات إلى مجموعة الوجهات السابقة ويزيلها منها.
بما أنّ الأنشطة السابقة هي مجموعة، فهي بنية بيانات "آخر ما يتم إدخاله هو أول ما يتم إخراجه". لذلك، يضيف NavController العناصر إلى أعلى المجموعة ويزيلها منه.
السلوك الأساسي
في ما يلي الحقائق الأساسية التي يجب مراعاتها بشأن سلوك مجموعة الوجهات السابقة:
- الوجهة الأولى: عندما يفتح المستخدِم التطبيق، يضيف
NavControllerالوجهة الأولى إلى أعلى مجموعة الوجهات السابقة. - الإضافة إلى المجموعة: تؤدي كل عملية استدعاء لـ
NavController.navigate()إلى إضافة الوجهة المحدّدة إلى أعلى المجموعة. - إزالة الوجهة الأعلى: يؤدي النقر على أعلى أو رجوع إلى استدعاء الطريقتَين
NavController.navigateUp()وNavController.popBackStack()على التوالي. وتؤدي هاتان الطريقتان إلى إزالة الوجهة الأعلى من المجموعة. لمزيد من المعلومات عن الفرق بين أعلى ورجوع، يُرجى الاطّلاع على صفحة مبادئ التنقّل.
الرجوع إلى الوجهة السابقة
تحاول الطريقة NavController.popBackStack() إزالة الوجهة الحالية
من مجموعة الوجهات السابقة والانتقال إلى الوجهة السابقة. ويؤدي ذلك فعليًا إلى إعادة المستخدِم خطوة واحدة إلى الوراء في سجلّ التنقّل. تعرض هذه الطريقة قيمة منطقية تشير إلى ما إذا تم الرجوع بنجاح إلى الوجهة السابقة.
الرجوع إلى وجهة معيّنة
يمكنك أيضًا استخدام popBackStack() للانتقال إلى وجهة معيّنة. لإجراء ذلك، استخدِم أحد النماذج الزائدة. هناك عدة نماذج زائدة تتيح لك تمرير معرّف، مثل id عدد صحيح أو route سلسلة. تأخذ هذه النماذج الزائدة المستخدِم إلى الوجهة المرتبطة بالمعرّف المحدّد. والأهم من ذلك أنّها تزيل كل العناصر من المجموعة أعلى تلك الوجهة.
تأخذ هذه النماذج الزائدة أيضًا قيمة منطقية inclusive. تحدّد هذه القيمة ما إذا كان على NavController أيضًا إزالة الوجهة المحدّدة من مجموعة الأنشطة السابقة بعد الانتقال إليها.
في ما يلي مقتطف قصير كمثال:
navController.popBackStack(R.id.destinationId, true)
هنا، يرجع NavController إلى الوجهة التي تحمل المعرّف destinationId الذي هو عدد صحيح. بما أنّ قيمة الوسيطة inclusive هي true، يزيل NavController أيضًا الوجهة المحدّدة من الأنشطة السابقة.
التعامل مع تعذُّر الرجوع إلى الوجهة السابقة
عندما تعرض popBackStack() القيمة false، يعرض استدعاء لاحق لـ NavController.getCurrentDestination() القيمة null. وهذا يعني أنّ التطبيق قد أزال الوجهة الأخيرة من مجموعة الوجهات السابقة. في هذه الحالة، لا يرى المستخدِم سوى شاشة فارغة.
يمكن أن يحدث ذلك في الحالات التالية:
- لم تُزِل
popBackStack()أي عنصر من المجموعة. - أزالت
popBackStack()وجهة من مجموعة الأنشطة السابقة وأصبحت المجموعة الآن فارغة.
لحلّ هذه المشكلة، عليك بعد ذلك الانتقال إلى وجهة جديدة أو استدعاء finish() في نشاطك لإنهاءه. يوضّح المقتطف التالي ذلك:
kotlin
...
if (!navController.popBackStack()) {
// Call finish() on your Activity
finish()
}
java
...
if (!navController.popBackStack()) {
// Call finish() on your Activity
finish();
}
الانتقال إلى وجهة معيّنة
لإزالة الوجهات من الأنشطة السابقة عند الانتقال من وجهة إلى أخرى، أضِف وسيطة popUpTo() إلى استدعاء الدالة navigate() المرتبط. تطلب popUpTo() من مكتبة Navigation إزالة بعض الوجهات من مجموعة الوجهات السابقة كجزء من استدعاء navigate(). قيمة المَعلمة هي معرّف وجهة في مجموعة الوجهات السابقة. يمكن أن يكون المعرّف id عدد صحيح أو route سلسلة.
يمكنك تضمين وسيطة للمَعلمة inclusive بقيمة true للإشارة إلى أنّه يجب أيضًا إزالة الوجهة التي حدّدتها في popUpTo() من الأنشطة السابقة.
لتنفيذ ذلك برمجيًا، مرِّر popUpTo() إلى navigate() كجزء من
NavOptions مع ضبط inclusive على true. تعمل هذه الطريقة في كلّ من Compose وViews.
حفظ الحالة عند الانتقال إلى وجهة معيّنة
عند استخدام popUpTo للانتقال إلى وجهة معيّنة، يمكنك اختياريًا حفظ مجموعة الوجهات السابقة وحالات جميع الوجهات التي تمت إزالتها من مجموعة الوجهات السابقة. يمكنك بعد ذلك استعادة مجموعة الوجهات السابقة والوجهات عند الانتقال إلى تلك الوجهة في وقت لاحق. يتيح لك ذلك الاحتفاظ بالحالة لوجهة معيّنة والحصول على
عدة مجموعات من الوجهات السابقة.
لإجراء ذلك برمجيًا، حدِّد saveState = true عند إضافة popUpTo إلى خيارات التنقّل.
يمكنك أيضًا تحديد restoreState = true في خيارات التنقّل لاستعادة مجموعة الوجهات السابقة والحالة المرتبطة بالوجهة تلقائيًا.
على سبيل المثال:
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
في ما يلي مثال كامل على ذلك في 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()، يُرجى الاطّلاع على
دليل التنقّل باستخدام الخيارات.
الإزالة باستخدام الإجراءات
عند التنقّل باستخدام إجراء، يمكنك اختياريًا إزالة وجهات إضافية من مجموعة الوجهات السابقة. على سبيل المثال، إذا كان تطبيقك يتضمّن مسار تسجيل دخول أوليًا، بعد أن يسجّل المستخدِم الدخول، عليك إزالة جميع الوجهات المرتبطة بتسجيل الدخول من الأنشطة السابقة حتى لا يعيد زر الرجوع المستخدِمين إلى مسار تسجيل الدخول.
موادّ إضافية للقراءة
لمزيد من المعلومات، يُرجى قراءة الصفحات التالية:
- التنقّل الدائري: تعرَّف على كيفية تجنُّب مجموعة الوجهات السابقة المكتظة في الحالات التي تكون فيها مسارات التنقّل دائرية.
- وجهات مربّعات الحوار: اطّلِع على كيفية إضافة وجهات مربّعات الحوار اعتبارات فريدة إلى طريقة إدارة مجموعة الوجهات السابقة.