توضّح الأقسام التالية استراتيجيات لحفظ سجلّ الرجوع وتخزين الحالة المرتبطة بالإدخالات في سجلّ الرجوع.
حفظ سجلّ الأنشطة السابقة
يُعدّ ضمان استمرار حالة التنقّل في تطبيقك خلال أحداث مراحل النشاط المختلفة، بما في ذلك تغييرات الإعدادات وإيقاف العملية نهائيًا، أمرًا بالغ الأهمية لتقديم تجربة جيدة للمستخدم. في Navigation 3، يمكنك التحكّم في سجلّ الأنشطة السابقة، لذا لا توجد إرشادات صارمة حول كيفية إنشائه أو حفظه. ومع ذلك، يوفّر الإصدار 3 من Navigation طريقة ملائمة تتيح لك حفظ حزمة الأنشطة السابقة: rememberNavBackStack.
استخدام rememberNavBackStack
تم تصميم الدالة المركّبة rememberNavBackStack لإنشاء الأنشطة السابقة التي تظل متاحة عند حدوث تغييرات في الإعدادات أو إيقاف العملية نهائيًا.
لكي يعمل rememberNavBackStack بشكل صحيح، يجب أن يستوفي كل مفتاح في الأنشطة السابقة المتطلبات التالية:
- تنفيذ واجهة
NavKey: يجب أن ينفّذ كل مفتاح في سجلّ الرجوع واجهةNavKey. تعمل هذه السمة كواجهة علامات تشير إلى المكتبة بأنّه يمكن حفظ المفتاح. - استخدام التعليق التوضيحي
@Serializable: بالإضافة إلى تنفيذNavKey، يجب وضع علامة@Serializableعلى الفئات والكائنات الرئيسية.
يوضّح المقتطف التالي عملية تنفيذ صحيحة للدالة rememberNavBackStack:
@Serializable data object Home : NavKey @Composable fun NavBackStack() { val backStack = rememberNavBackStack(Home) }
تذكُّر الأنشطة السابقة مع الأنواع الفرعية من NavKey
تعرض الدالة المركّبة rememberNavBackStack عنصر NavBackStack<NavKey>.
إذا كان تطبيقك يحدّد نوعًا فرعيًا خاصًا به من NavKey ترث منه جميع مفاتيحه، يمكنك الحفاظ على هذا النوع من خلال تنفيذ دالة تذكُّر مخصّصة، كما يلي:
@Serializable sealed interface MyAppNavKey : NavKey @Serializable data object ScreenA: MyAppNavKey @Serializable data class ScreenB(val id: String): MyAppNavKey @Composable fun rememberMyAppNavBackStack(vararg elements: MyAppNavKey): NavBackStack<MyAppNavKey> { return rememberSerializable(serializer = serializer()) { NavBackStack(*elements) } } @Composable fun MyApp() { // defaultNavBackStack is NavBackStack<NavKey> val defaultNavBackStack = rememberNavBackStack(ScreenA) // myAppNavBackStack is NavBackStack<MyAppNavKey> val myAppNavBackStack = rememberMyAppNavBackStack(ScreenA) }
للاطّلاع على المزيد من الأمثلة، بما في ذلك كيفية التعامل مع تعدد الأشكال المفتوح، يُرجى الاطّلاع على
NavBackStackSamples.
بديل: التخزين في ViewModel
هناك طريقة أخرى لإدارة الأنشطة السابقة، وهي تخزينه في ViewModel.
للحفاظ على البيانات عند إيقاف العملية نهائيًا عند استخدام ViewModel أو أي مساحة تخزين مخصّصة أخرى، عليك اتّباع الخطوات التالية:
- التأكّد من إمكانية تسلسل مفاتيح التنقّل: كما هو الحال مع
rememberNavBackStack، يجب أن تكون مفاتيح التنقّل قابلة للتسلسل. - التعامل مع التسلسل وإلغاء التسلسل يدويًا: أنت المسؤول عن حفظ التمثيل المتسلسل لكل مفتاح يدويًا في مساحة التخزين الدائمة (مثل
SharedPreferencesأو قاعدة بيانات أو ملف) وإلغاء تسلسله منها عندما ينتقل تطبيقك إلى الخلفية أو تتم استعادته.
تحديد نطاق ViewModel ثانية إلى NavEntry ثانية
تُستخدَم ViewModels للاحتفاظ بالحالة المرتبطة بواجهة المستخدم عند حدوث تغييرات في الإعدادات، مثل تدوير الشاشة. تكون ViewModels تلقائيًا ضمن نطاق أقرب ViewModelStoreOwner، والذي يكون عادةً Activity أو Fragment.
ومع ذلك، قد تحتاج إلى تحديد نطاق ViewModel ليشمل NavEntry معيّنًا (أي شاشة أو وجهة معيّنة) في حزمة الأنشطة السابقة، بدلاً من Activity بأكمله. يضمن ذلك الاحتفاظ بحالة ViewModel فقط عندما يكون NavEntry المعيّن جزءًا من الأنشطة السابقة، ويتم محوها عند إزالة NavEntry.
توفّر مكتبة الإضافات androidx.lifecycle:lifecycle-viewmodel-navigation3 NavEntryDecorator تسهّل ذلك. يوفّر هذا العنصر الزخرفي ViewModelStoreOwner لكل NavEntry. عند إنشاء ViewModel داخل محتوى NavEntry (على سبيل المثال، باستخدام viewModel() في Compose)، يتم تلقائيًا تحديد نطاق ViewModel ليطابق مفتاح NavEntry المحدّد في سجلّ الأنشطة السابقة. وهذا يعني أنّه يتم إنشاء
ViewModel عند إضافة NavEntry إلى الأنشطة السابقة،
ويتم محوه عند إزالته.
لاستخدام NavEntryDecorator لتحديد نطاق ViewModels إلى NavEntrys، اتّبِع الخطوات التالية:
- أضِف الاعتمادية
androidx.lifecycle:lifecycle-viewmodel-navigation3إلى ملفapp/build.gradle.kts. - أضِف القيمة التلقائية
rememberSaveableStateHolderNavEntryDecorator()إلى قائمةentryDecoratorsعند إنشاءNavDisplay. - أضِف
rememberViewModelStoreNavEntryDecorator()إلى قائمةentryDecorators.
NavDisplay( entryDecorators = listOf( // Add the default decorators for managing scenes and saving state rememberSaveableStateHolderNavEntryDecorator(), // Then add the view model store decorator rememberViewModelStoreNavEntryDecorator() ), backStack = backStack, entryProvider = entryProvider { }, )