استعادة الحالة في التطبيقات المحمولة: ما هي، آليتها ومبدأ عملها

المؤلف: IT Sectr نُشر: 2026-05-18 وقت القراءة: 8 دق

استعادة الحالة (State Restoration) هي آلية في أنظمة التشغيل المحمولة تسمح بحفظ واستعادة واجهة مستخدم التطبيق بعد إعادة تشغيله أو تصغيره. يحفظ النظام حالة واجهة المستخدم في الذاكرة أو التخزين الدائم ويستعيدها عند إعادة الفتح. وفقًا لـ Android Developers (2025)، فإن استعادة الحالة إلزامية للتطبيقات التي تسعى إلى تجربة مستخدم عالية الجودة. استعادة الحالة ضرورية لمنع فقدان البيانات عند إنهاء التطبيق بشكل غير متوقع.

الملامح الرئيسية

  • استعادة الحالة — آلية لحفظ واستعادة واجهة المستخدم عند إعادة تشغيل التطبيق، تمنع فقدان بيانات المستخدم والسياق.
  • دورة الحياة — يتم تفعيل الاستعادة عند إعادة التشغيل بعد التصغير أو إعادة تشغيل الجهاز أو إغلاق التطبيق بواسطة النظام.
  • المنصات — يدعم iOS استعادة الحالة عبر UIKit (NSUserActivity، UIStateRestoring)، ويدعمها Android عبر SavedStateHandle وViewModel.
  • البيانات المراد حفظها — موضع التمرير، البيانات المدخلة في النماذج، حالة التنقل، المحتوى المتعدد الوسائط والعناصر المحددة.
  • التنفيذ — يتطلب تسلسل الحالة في Bundle أو NSData واستعادتها في طرق دورة الحياة المناسبة.

ما هي استعادة الحالة؟

استعادة الحالة (State Restoration) هي آلية نظام تسمح بحفظ الحالة الحالية لواجهة مستخدم التطبيق واستعادتها بعد إنهائه أو إعادة تشغيله. عندما يقوم المستخدم بتصغير تطبيق أو يغلقه النظام لتحرير الموارد، تلتقط استعادة الحالة معلمات واجهة المستخدم الرئيسية وتحفظها في تخزين مشفر.

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

تعمل الآلية على مستوى النظام وهي مدعومة من قبل كلتا المنصتين المحمولتين الرئيسيتين. يوفر iOS استعادة الحالة عبر NSUserActivity وبروتوكول UIStateRestoring، بينما يوفرها Android عبر SavedStateHandle في مكونات Jetpack المعمارية وViewModel. يختلف التنفيذ لكن المفهوم متطابق.

كيف تعمل استعادة الحالة؟

تنقسم عملية استعادة الحالة إلى مرحلتين: الحفظ والاستعادة. في مرحلة الحفظ، يستدعي النظام طرق دورة الحياة المناسبة، حيث يجب على التطبيق تسلسل الحالة الحالية لواجهة المستخدم إلى تمثيل مضغوط. في مرحلة الاستعادة، يعيد النظام البيانات المحفوظة ويقوم التطبيق بإلغاء تسلسلها لاستعادة واجهة المستخدم.

آلية حفظ الحالة

يبدأ النظام عملية الحفظ عندما ينتقل التطبيق إلى الخلفية أو يتلقى إشارة بإنهاء وشيك. في iOS، يتم استدعاء طريقة encodeRestorableState الخاصة بـ UIViewController؛ في Android، يتم استدعاء onSaveInstanceState الخاص بـ Activity أو الحفظ عبر SavedStateHandle. يتم تسلسل البيانات إلى تنسيق يدعم الأنواع البدائية: السلاسل النصية والأرقام ومصفوفات البايت وكائنات Parcelable.

يجب أن يكون حجم البيانات المحفوظة ضئيلاً — يفرض النظام قيودًا على حجم حزمة الحالة المحفوظة. في Android، يبلغ الحد الأقصى حوالي 50 كيلوبايت لكل عملية. يؤدي تجاوز الحد إلى استثناء TransactionTooLargeException. لذلك، يوصي المعماريون بحفظ المعرفات والمفاتيح فقط، وتحميل البيانات الكاملة من التخزين الدائم عند الاستعادة.

استعادة واجهة المستخدم من الحالة المحفوظة

أثناء الاستعادة، يمرر النظام حزمة البيانات المحفوظة إلى التطبيق في وقت التشغيل. في iOS، يتم استدعاء طريقة decodeRestorableState؛ في Android، يتم استخدام onRestoreInstanceState أو القراءة من SavedStateHandle. يستخرج التطبيق المعرفات والمفاتيح من الحزمة ويستعيد واجهة المستخدم: موضع التمرير والعناصر المحددة والبيانات المدخلة.

من المهم ملاحظة أن الاستعادة قد تحدث في عملية جديدة. إذا تم تفريغ التطبيق بالكامل من الذاكرة، يتم إنشاء العملية من جديد وتكون جميع الكائنات في الذاكرة غائبة. لذلك، يجب أن تكون الحالة قابلة للتسلسل ومستقلة عن سياق وقت التشغيل للجلسة السابقة. هذا أمر بالغ الأهمية بشكل خاص للنماذج الكبيرة ذات حقول الإدخال المتعددة والواجهات الطويلة متعددة الصفحات.

kotlin
class MainActivity : AppCompatActivity() {
    private var searchQuery: String = ""

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        outState.putString("search_query", searchQuery)
    }

    override fun onRestoreInstanceState(savedState: Bundle) {
        super.onRestoreInstanceState(savedState)
        searchQuery = savedState.getString("search_query", "")!!
        restoreSearchUI(searchQuery)
    }
}

استعادة الحالة على iOS وAndroid

يختلف تنفيذ استعادة الحالة بشكل كبير بين المنصات. يستخدم iOS نهجًا تصريحيًا عبر القصص المصورة (storyboards) وبروتوكولات UIKit، بينما يستخدم Android نهجًا أمريًا عبر طرق دورة حياة Activity والمكونات المعمارية Jetpack. يعتمد اختيار النهج على المنصة المستهدفة وهندسة التطبيق.

استعادة الحالة في iOS (UIKit)

في iOS، تُبنى استعادة الحالة على ثلاثة مكونات: UIApplication يدير العملية الشاملة، UIApplication يطبق بروتوكول UIStateRestoring، وNSUserActivity يخزن بيانات استعادة التنقل. لتمكينها، يجب تعيين restorationIdentifier على UIViewController وتنفيذ encodeRestorableState وdecodeRestorableState.

يحفظ iOS تلقائيًا حالة وحدة التحكم في التنقل (UINavigationController) وجميع ViewControllers المتداخلة إذا كان لديها restorationIdentifier مضبوط. يدير النظام مكدس التنقل ويستعيده إلى حالته الأصلية. ومع ذلك، يجب على المطور حفظ البيانات داخل وحدات التحكم (النص المدخل، موضع التمرير) بشكل صريح.

استعادة الحالة في Android (SavedStateHandle)

في Android، يُبنى النهج الحديث لاستعادة الحالة على SavedStateHandle — مكون من مكتبة AndroidX Lifecycle. يمكن الوصول إلى SavedStateHandle داخل ViewModel ويقوم تلقائيًا بحفظ واستعادة البيانات عند تغييرات التكوين (تدوير الشاشة) وإعادة تشغيل العملية. يتم تخزين البيانات في Bundle ويتم تسلسلها تلقائيًا.

يتصرف SavedStateHandle كـ مخزن مفتاح-قيمة مع دعم LiveData. عند تغييرات التكوين، يتم حفظ البيانات واستعادتها تلقائيًا. لدعم إعادة تشغيل العملية، يجب إنشاء ViewModel عبر SavedStateViewModelFactory — مما يسمح لـ ViewModel بالبقاء بعد إنهاء التطبيق بالكامل.

kotlin
class SearchViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    companion object {
        private val KEY_QUERY = string("search_query")
    }

    fun getSearchQuery(): String? = savedStateHandle[KEY_QUERY]

    fun saveSearchQuery(query: String) {
        savedStateHandle[KEY_QUERY] = query
    }
}

تنفيذ استعادة الحالة في الكود

يتطلب التنفيذ العملي لاستعادة الحالة مراعاة عدة جوانب: اختيار التخزين المناسب، تحديد حجم البيانات المراد حفظها واختبار سيناريوهات الإنهاء المختلفة. دعنا نستعرض تنفيذًا خطوة بخطوة لـ تطبيق Flutter باستخدام حزمة state_restoration.

dart
class RestorableSearchField extends RestorableProperty<String> {
  String _value = '';

  @override
  String get value => _value;

  @override
  void set value(String newValue) {
    if (_value != newValue) {
      _value = newValue;
      notifyListeners();
    }
  }

  @override
  String? toPrimitives() => _value;

  @override
  void fromPrimitives(String? data) {
    _value = data ?? '';
  }
}

عند التنفيذ، من المهم تذكر حدود الحفظ. ليست كل حقول واجهة المستخدم تحتاج إلى استعادة. موضع التمرير في قائمة طويلة — نعم. حالة الرسوم المتحركة المؤقتة — لا. يجب على المطور أن يختار بوعي أي البيانات ضرورية لتجربة المستخدم وأيها يمكن إعادة تعيينها بأمان دون فقدان الراحة.

اختبار استعادة الحالة هو مهمة منفصلة تتطلب محاكاة إنهاء العملية. على Android، يمكن القيام بذلك عبر الأمر adb shell am kill؛ على iOS، عبر محاكاة الإنهاء في Xcode. توفر أطر اختبار واجهة المستخدم مثل Espresso وXCTest طرقًا خاصة للتحقق من استعادة الحالة.

أفضل ممارسات استعادة الحالة

القاعدة الأولى — احفظ المعرفات، وليس البيانات. بدلاً من حفظ الكائن الكامل بمئة حقل، احفظ معرفه الفريد، وعند الاستعادة قم بتحميل البيانات الفعلية من قاعدة البيانات أو API. يوفر هذا مساحة في Bundle ويضمن نضارة البيانات في وقت الاستعادة.

القاعدة الثانية — اختبر جميع السيناريوهات. تحقق من الاستعادة بعد تدوير الشاشة، بعد التصغير والعودة بعد ساعة، بعد إنهاء التطبيق من قبل النظام بسبب نقص الذاكرة. قد يتصرف كل سيناريو بشكل مختلف اعتمادًا على حالة نظام التشغيل والموارد المتاحة.

القاعدة الثالثة — استخدم آليات النظام، وليس آليات مخصصة. يوفر iOS وAndroid واجهات برمجة تطبيقات مدمجة لاستعادة الحالة محسنة لمنصتهما المحددة. يمكن أن يؤدي التنفيذ المخصص عبر SharedPreferences أو UserDefaults إلى مشاكل في المزامنة وسلوك غير متوقع أثناء الاستعادة.

القاعدة الرابعة — تعامل مع غياب الحالة. عند التشغيل الأول أو بعد مسح البيانات، قد تكون الحالة غائبة. يجب أن تعمل واجهة المستخدم بشكل صحيح في حالتها الأولية دون رمي استثناءات. تحقق من جميع البيانات المحفوظة للتأكد من أنها غير فارغة قبل الاستخدام وقدم قيمًا افتراضية.

القاعدة الخامسة — وثق المفاتيح المحفوظة. عندما يحتوي المشروع على عشرات الشاشات وتحفظ كل منها عدة حقول، ينشأ الفوضى بدون إدارة مركزية للمفاتيح. أنشئ فئة واحدة أو ملفًا بثوابت المفاتيح لاستعادة الحالة في كل وحدة. هذا يبسط الصيانة ويمنع الكتابة فوق البيانات العرضية أثناء إعادة الهيكلة.

الأسئلة الشائعة

ما هي استعادة الحالة في التطبيقات المحمولة؟

استعادة الحالة هي آلية لحفظ واستعادة واجهة مستخدم التطبيق بعد إعادة تشغيله أو تصغيره، مما يمنع فقدان البيانات وسياق عمل المستخدم.

كيف تختلف استعادة الحالة عن الحفظ في قاعدة البيانات؟

تحفظ استعادة الحالة الحالة المؤقتة لواجهة المستخدم (موضع التمرير، البيانات المدخلة في النموذج)، بينما تخزن قاعدة البيانات بيانات المستخدم الدائمة. تستخدم استعادة الحالة آليات النظام (Bundle، NSData) مع قيود على الحجم.

كيف تنفذ استعادة الحالة في Android؟

استخدم SavedStateHandle في ViewModel من AndroidX Lifecycle. يقوم تلقائيًا بحفظ البيانات عند التصغير واستعادتها عند العودة. لدعم إعادة التشغيل الكامل، استخدم SavedStateViewModelFactory.

كيف تنفذ استعادة الحالة في iOS؟

قم بتعيين restorationIdentifier على UIViewController ونفذ طريقتي encodeRestorableState وdecodeRestorableState. للتنقل، استخدم NSUserActivity مع الحفاظ على المسار في مكدس وحدات التحكم.

ما البيانات التي يجب حفظها أثناء استعادة الحالة؟

احفظ المعرفات، وليس البيانات الكاملة: معرف العنصر المحدد، استعلام البحث، موضع التمرير، حالات المفاتيح. تجنب حفظ الكائنات الكبيرة والصور.

الخلاصة

  • استعادة الحالة — آلية نظام لحفظ واستعادة واجهة المستخدم عند إعادة تشغيل التطبيق، ضرورية لتجربة المستخدم.
  • iOS — يستخدم بروتوكول UIStateRestoring وNSUserActivity لحفظ التنقل وبيانات وحدات التحكم.
  • Android — يوفر SavedStateHandle في ViewModel للحفظ والاستعادة التلقائيين للحالة.
  • Flutter — يدعم RestorableProperty وRestorableStatefulWidget لحفظ حالة الأدوات.
  • القيود — حجم البيانات المحفوظة محدود (~50 كيلوبايت في Android)، احفظ المعرفات فقط.
  • الاختبار — من الضروري التحقق من جميع السيناريوهات: تدوير الشاشة، التصغير، إنهاء العملية من قبل النظام.
  • الاستراتيجية — استخدم واجهات برمجة التطبيقات للنظام بدلاً من التنفيذ المخصص عبر الملفات أو SharedPreferences.

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا