حفظ حالة التنقّل وإدارتها

توضِّح الأقسام التالية استراتيجيات حفظ الحزمة الخلفية و تخزين الحالة المرتبطة بالإدخالات في الحزمة الخلفية.

حفظ الحزمة الخلفية

إنّ ضمان استمرار حالة التنقّل في تطبيقك على مستوى أحداث دورة الحياة المختلفة، بما في ذلك تغييرات الإعدادات وانتهاء العملية، هو أمر مهم لتوفير تجربة مستخدم جيدة. في Navigation 3، تكون حزمة التطبيقات التي سبق لك فتحها ملكًا لك، لذا لا تتوفّر إرشادات صارمة حول كيفية إنشائها أو حفظها. ومع ذلك، يوفّر التنقّل 3 طريقة سهلة تمنحك حزمة "الرجوع" التي يمكن حفظها: rememberNavBackStack.

استخدام rememberNavBackStack

تم تصميم الدالة القابلة للتجميع rememberNavBackStack لإنشاء ملف rememberNavBackStack احتياطي يبقى محفوظًا على الرغم من تغييرات الإعدادات وإيقاف العملية.

لكي يعمل rememberNavBackStack بشكل صحيح، يجب أن يلتزم كل مفتاح في الحزمة الخلفية بمتطلبات معيّنة:

  • تنفيذ واجهة NavKey: يجب أن ينفذ كل مفتاح في الحزمة الخلفية واجهة NavKey. ويعمل هذا العنصر كواجهة علامة تشير إلى المكتبة بأنّه يمكن حفظ المفتاح.
  • توفُّر التعليق التوضيحي @Serializable: بالإضافة إلى تنفيذ NavKey، يجب وضع علامة على الفئات والكائنات الرئيسية باستخدام التعليق التوضيحي @Serializable.

يعرض المقتطف التالي تنفيذًا صحيحًا لـ rememberNavBackStack:

@Serializable
data object Home : NavKey

@Composable
fun NavBackStack() {
    val backStack = rememberNavBackStack(Home)
}

البديل: التخزين في 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() في ميزة "الإنشاء")، يتم حصره تلقائيًا بمفتاح NavEntry المحدّد هذا في الحزمة الخلفية. وهذا يعني أنّه يتم إنشاء ViewModel عند إضافة NavEntry إلى الحزمة الخلفية، ويتم محو القيمة عند إزالتها.

لاستخدام NavEntryDecorator لتحديد نطاق ViewModel إلى NavEntry، اتّبِع الخطوات التالية:

  1. أضِف التبعية androidx.lifecycle:lifecycle-viewmodel-navigation3 إلىملف app/build.gradle.kts.
  2. أضِف rememberSavedStateNavEntryDecorator() إلى قائمة entryDecorators عند إنشاء NavDisplay.
  3. أضِف أدوات تزيين أخرى إلى NavDisplay.

NavDisplay(
    entryDecorators = listOf(
        // Add the default decorators for managing scenes and saving state
        rememberSceneSetupNavEntryDecorator(),
        rememberSavedStateNavEntryDecorator(),
        // Then add the view model store decorator
        rememberViewModelStoreNavEntryDecorator()
    ),
    backStack = backStack,
    entryProvider = entryProvider { },
)