جارٍ حفظ الحالة مع الأجزاء

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

يوضّح الجدول التالي العمليات التي تؤدي إلى فقدان العنصر المجزّأ لحالة، بالإضافة إلى ما إذا كانت الأنواع المختلفة للحالة تستمر خلال تلك التغييرات. في ما يلي أنواع الحالات المذكورة في الجدول:

  • المتغيّرات: المتغيّرات المحلية في المقتطف
  • حالة العرض: أي بيانات تملكها طريقة عرض واحدة أو أكثر في المقتطف
  • SavedState: بيانات متأصلة في مثيل المقتطف هذا والتي يجب حفظها في onSaveInstanceState()
  • NonConfig: البيانات التي يتمّ استردادها من مصدر خارجي، مثل خادم أو مستودع محلي، أو البيانات التي أنشأها المستخدم والتي يتمّ إرسالها إلى خادم بعد تأكيدها

غالبًا ما يتم التعامل مع المتغيّرات بالطريقة نفسها المتّبعة مع SavedState، إلا أنّ الجدول التالي يميّز بينهما لتوضيح تأثير العمليات المختلفة في كلٍّ منها.

العملية المتغيّرات عرض الحالة SavedState عدم ضبط
تمت الإضافة إلى الحزمة الخلفية x
تغيير الإعدادات x
إيقاف العملية نهائيًا/إعادة إنشائها x ✓*
تمت إزالة الملف بدون إضافته إلى الحزمة الخلفية x x x x
انتهى المضيف x x x x

* يمكن الاحتفاظ بحالة NonConfig على الرغم من إنهاء العملية باستخدام وحدة الحالة المحفوظة لـ ViewModel.

الجدول 1: العمليات المختلفة التي تؤدي إلى إتلاف الأجزاء والتأثيرات التي تحدثها في أنواع الحالات المختلفة

لنلقِ نظرة على مثال محدّد. لنفترض أنّ هناك شاشة تنشئ سلسلة عشوائية وتعرضها في TextView، وتوفر خيارًا لتعديل السلسلة قبل إرسالها إلى صديق:

تطبيق لإنشاء نص عشوائي يعرض
            أنواعًا مختلفة من الحالات
الشكل 1. تطبيق لإنشاء نص عشوائي يعرض أنواعًا مختلفة من الحالات

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

البيانات النوع نوع الولاية الوصف
seed Long NonConfig قيمة الإدخال العشوائية تُستخدَم لإنشاء عمل صالح جديد بشكل عشوائي. يتم إنشاؤه عند إنشاء ViewModel.
randomGoodDeed String SavedState + متغيّر يتم إنشاؤه عند إنشاء الجزء لأول مرة. يتم حفظ السمة randomGoodDeed لضمان أن يرى المستخدمون العمل الصالح العشوائي نفسه حتى بعد انتهاء العملية وإعادة الإنشاء.
isEditing Boolean SavedState + متغيّر تم ضبط العلامة المنطقية على true عندما يبدأ المستخدم في التعديل. يتم حفظ isEditing للتأكّد من بقاء جزء التعديل في الشاشة مرئيًا عند إعادة إنشاء الجزء.
النص المعدَّل Editable عرض الحالة (مملوكة EditText) النص المعدَّل في طريقة العرض EditText تحفظ طريقة العرض EditText هذا النص لضمان عدم فقدان تغييرات المستخدم الجارية.

الجدول 2: يشير إلى ضرورة أن يديره تطبيق منشئ النص العشوائي.

توضّح الأقسام التالية كيفية إدارة حالة بياناتك بشكلٍ سليم من خلال العمليات المدمِّرة.

عرض الحالة

تتحمّل المشاهدات مسؤولية إدارة حالتها. على سبيل المثال، عندما يقبل الجدول الاطّلاع إدخال المستخدم، تقع على عاتق الجدول الاطّلاع مسؤولية حفظ هذا الإدخال واستعادته للتعامل مع تغييرات الإعدادات. تحتوي جميع طرق العرض التي يوفّرها إطار عمل Android على التنفيذ الخاص بها للسمتَين onSaveInstanceState() وonRestoreInstanceState()، لذا لن تحتاج إلى إدارة حالة العرض ضمن الجزء.

على سبيل المثال، في السيناريو السابق، يتم الاحتفاظ بالسلسلة المعدَّلة في ملف EditText. يعرف EditText قيمة النص الذي يعرضه، بالإضافة إلى التفاصيل الأخرى، مثل بداية ونهاية أي نص محدد.

تحتاج طريقة العرض إلى معرّف للحفاظ على حالتها. يجب أن يكون هذا المعرّف فريدًا ضمن القطعة وترتيب عرضها الهرمي. لا يمكن لعمليات العرض التي لا تتضمّن معرّفًا الاحتفاظ بحالتها.

<EditText
    android:id="@+id/good_deed_edit_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

كما هو موضّح في الجدول 1، تحفظ طرق العرض ViewState وتستعيدها من خلال جميع العمليات التي لا تزيل المقتطف أو تُدمِر المضيف.

SavedState

يكون المقتطف مسؤولاً عن إدارة كميات صغيرة من الحالة الديناميكية التي تكون جزءًا لا يتجزأ من طريقة عمل المقتطف. ويمكنك الاحتفاظ بالبيانات المتسلسلة بسهولة باستخدام Fragment.onSaveInstanceState(Bundle). على غرار Activity.onSaveInstanceState(Bundle)، يتم الاحتفاظ بالبيانات التي تضعها في الحِزمة من خلال تغييرات الإعدادات وانتهاء عملية الإنشاء وإعادة إنشائها، وتتوفّر في طرق العنصر المكوّن onCreate(Bundle)، onCreateView(LayoutInflater, ViewGroup, Bundle)، و onViewCreated(View, Bundle).

استنادًا إلى المثال السابق، randomGoodDeed هو العقد الذي يتم عرضه للمستخدم، وisEditing هو علامة لتحديد ما إذا كان القطعة يعرض EditText أو يخفيه. يجب تثبيت هذه الحالة المحفوظة باستخدام onSaveInstanceState(Bundle)، كما هو موضّح في المثال التالي:

Kotlin

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putBoolean(IS_EDITING_KEY, isEditing)
    outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed)
}

Java

@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putBoolean(IS_EDITING_KEY, isEditing);
    outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed);
}

لاستعادة الحالة في onCreate(Bundle)، عليك استرداد القيمة المخزّنة من الحزمة:

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    isEditing = savedInstanceState?.getBoolean(IS_EDITING_KEY, false)
    randomGoodDeed = savedInstanceState?.getString(RANDOM_GOOD_DEED_KEY)
            ?: viewModel.generateRandomGoodDeed()
}

Java

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
        isEditing = savedInstanceState.getBoolean(IS_EDITING_KEY, false);
        randomGoodDeed = savedInstanceState.getString(RANDOM_GOOD_DEED_KEY);
    } else {
        randomGoodDeed = viewModel.generateRandomGoodDeed();
    }
}

كما هو موضّح في الجدول 1، يُرجى العلم أنّه يتم الاحتفاظ بالمتغيّرات عند وضع ال fragment في الحزمة الخلفية. ويضمن التعامل معها كحالة محفوظة باستمراريتها في جميع العمليات المدمرة.

عدم ضبط

يجب وضع بيانات NonConfig خارج المقتطف، مثل ViewModel. في المثال السابق أعلاه، يتم إنشاء seed (حالة NonConfig) في ViewModel. يملك ViewModel منطق الحفاظ على حالته.

Kotlin

public class RandomGoodDeedViewModel : ViewModel() {
    private val seed = ... // Generate the seed

    private fun generateRandomGoodDeed(): String {
        val goodDeed = ... // Generate a random good deed using the seed
        return goodDeed
    }
}

Java

public class RandomGoodDeedViewModel extends ViewModel {
    private Long seed = ... // Generate the seed

    private String generateRandomGoodDeed() {
        String goodDeed = ... // Generate a random good deed using the seed
        return goodDeed;
    }
}

تسمح فئة ViewModel بشكلٍ أساسي للبيانات بالبقاء محفوظة عند إجراء تغييرات على الإعدادات، مثل عمليات تدوير الشاشة، وتبقى في الذاكرة عند وضع القطعة في الحزمة الخلفية. بعد إنهاء العملية وإعادة إنشائها، تتم إعادة إنشاء ViewModel وإنشاء seed جديد. تؤدي إضافة SavedState وحدة إلى ViewModel إلى السماح ViewModel بالحفاظ على الحالة البسيطة من خلال وفاة العملية وإعادة إنشائها.

مصادر إضافية

لمزيد من المعلومات عن إدارة حالة المقتطف، يُرجى الاطّلاع على المراجع التالية الإضافية.

الدروس التطبيقية حول الترميز

الأدلّة