توضّح الأقسام التالية استراتيجيات حفظ الأنشطة السابقة وتخزين الحالة المرتبطة بالإدخالات في الأنشطة السابقة.
حفظ الأنشطة السابقة
لضمان تقديم تجربة جيدة للمستخدم، من الضروري الحفاظ على حالة التنقّل في تطبيقك خلال مختلف الأحداث التي تتم في مراحل النشاط، بما في ذلك تغييرات الإعدادات وإيقاف العملية نهائيًا. في Navigation 3، يمكنك التحكّم في الأنشطة السابقة، لذا لا توجد إرشادات صارمة
حول كيفية إنشائها أو حفظها. ومع ذلك، يوفّر Navigation 3
طريقة ملائمة تتيح لك حفظ الأنشطة السابقة:
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 ترث منه جميع مفاتيحه، يمكنك الحفاظ على هذا النوع من خلال تنفيذ دالة remember مخصّصة، على النحو التالي:
@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)، يتم تلقائيًا تحديد نطاقه لمفتاح 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 { }, )