مراحل نشاط الأجزاء

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

لإدارة مراحل النشاط، يستخدم Fragment السمة LifecycleOwner التي تعرض عنصر Lifecycle يمكنك الوصول إليه من خلال طريقة getLifecycle().

يتم تمثيل كل ولاية Lifecycle ممكنة في تعداد Lifecycle.State.

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

بدلاً من استخدام LifecycleObserver، تتضمّن الفئة Fragment طرق استدعاء تتوافق مع كل تغيير من التغييرات في مراحل نشاط الجزء. وهي تشمل onCreate() وonStart() وonResume() وonPause() onStop() وonDestroy().

يتضمّن عرض الجزء Lifecycle منفصلة تتم إدارتها بشكل مستقل عن طريقة عرض Lifecycle للجزء. تحتفظ الأجزاء بعنصر LifecycleOwner للعرض، والذي يمكن الوصول إليه باستخدام getViewLifecycleOwner() أو getViewLifecycleOwnerLiveData(). يُعدّ الوصول إلى Lifecycle لطريقة العرض مفيدًا في الحالات التي يجب أن يعمل فيها أحد مكوّنات الوعي بمراحل النشاط فقط أثناء وجود عرض جزء معيّن، مثل ملاحظة LiveData التي من المفترض أن يظهر على الشاشة فقط.

يناقش هذا الموضوع دورة حياة Fragment بالتفصيل، ويشرح بعض القواعد التي تحدّد حالة دورة حياة الجزء، ويعرض العلاقة بين حالات Lifecycle واستدعاءات مراحل نشاط الجزء.

الأجزاء وإدارة الأجزاء

عند إنشاء مثيل للجزء، يبدأ بالحالة INITIALIZED. لكي ينتقل الجزء خلال بقية مراحل نشاطه، يجب إضافته إلى FragmentManager. وتكون FragmentManager مسؤولة عن تحديد الحالة التي يجب أن يكون فيها الجزء ثم نقلها إلى تلك الحالة.

بالإضافة إلى دورة حياة الجزء، تكون FragmentManager مسؤولة أيضًا عن إرفاق الأجزاء بنشاط المضيف وفصلها عندما لا يكون الجزء قيد الاستخدام. تحتوي الفئة Fragment على طريقتين لرد الاتصال، وهما onAttach() وonDetach()، ويمكنك إلغاءهما لأداء العمل عند وقوع أي من هذين الحدثين.

يتم استدعاء استدعاء onAttach() عند إضافة الجزء إلى FragmentManager وإرفاقه بنشاط المضيف. في هذه المرحلة، يكون الجزء نشطًا، وتدير FragmentManager حالة مراحل نشاطه. في هذه المرحلة، تعرض طرق FragmentManager مثل findFragmentById() هذا الجزء.

يتم استدعاء onAttach() دائمًا قبل أي تغييرات في حالة دورة الحياة.

يتم استدعاء استدعاء onDetach() عند إزالة الجزء من FragmentManager ويتم فصله عن نشاط المضيف. لم يعُد الجزء نشطًا ولا يمكن استرداده باستخدام findFragmentById().

يتم استدعاء onDetach() دائمًا بعد أي تغييرات في حالة دورة الحياة.

يُرجى العلم أنّ عمليات معاودة الاتصال هذه غير مرتبطة بطريقتَي FragmentTransaction attach() وdetach(). لمزيد من المعلومات حول هذه الطرق، راجع المعاملات المجزأة.

حالات مراحل نشاط التجزئة وحالات معاودة الاتصال

عند تحديد حالة مراحل نشاط الجزء، يراعي FragmentManager ما يلي:

  • يتم تحديد الحد الأقصى لحالة الجزء من خلال FragmentManager. ولا يمكن أن يتقدّم الجزء إلى ما بعد حالة FragmentManager.
  • كجزء من FragmentTransaction، يمكنك ضبط الحدّ الأقصى لمراحل النشاط على جزء باستخدام setMaxLifecycle() .
  • لا يمكن أبدًا أن تكون حالة دورة حياة الجزء أكبر من المستوى الرئيسي له. على سبيل المثال، يجب بدء نشاط أو جزء رئيسي قبل أن يبدأ بأجزاءه الفرعية. وبالمثل، يجب إيقاف الأجزاء الفرعية قبل الجزء الرئيسي أو النشاط الرئيسي.
حالات دورة حياة الجزء وعلاقتها بكل من استدعاءات دورة حياة الجزء ودورة حياة عرض الجزء
الشكل 1. حالات Lifecycle للجزء وعلاقتها بكل من استدعاءات دورة حياة الجزء وعرض Lifecycle للجزء.

يوضّح الشكل 1 كل حالة من حالات Lifecycle للجزء وكيفية ارتباطها بكل من استدعاءات دورة حياة الجزء وعرض Lifecycle للجزء.

ومع تقدم الجزء خلال دورة حياته، يتحرك لأعلى ولأسفل خلال حالاته. على سبيل المثال، ينتقل الجزء الذي تتم إضافته إلى أعلى الحزمة الخلفية من CREATED إلى STARTED إلى RESUMED. وعلى العكس من ذلك، عندما ينبثق جزء من الحزمة الخلفية، يتحرك للأسفل خلال تلك الحالات، بدءًا من RESUMED إلى STARTED إلى CREATED وأخيرًا DESTROYED.

انتقالات الحالة الصاعدة

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

تم إنشاء الجزء

عندما يصل الجزء إلى حالة CREATED، تتم إضافته إلى FragmentManager وتم استدعاء الطريقة onAttach() من قبل.

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

تؤدي عملية النقل هذه إلى استدعاء onCreate() لمعاودة الاتصال. يتلقى معاودة الاتصال أيضًا وسيطة savedInstanceState Bundle تحتوي على أي حالة تم حفظها سابقًا في onSaveInstanceState(). ملاحظة: يتضمّن savedInstanceState القيمة null في المرة الأولى التي يتم فيها إنشاء الجزء، ولكنّها دائمًا لا تكون فارغة في الاقتراحات اللاحقة، حتى إذا لم تلغ السمة onSaveInstanceState(). راجع حفظ الحالة باستخدام الأجزاء للحصول على مزيد من التفاصيل.

تم إنشاء الجزء وبدء العرض

لا يتم إنشاء عرض الجزء Lifecycle إلا عندما يوفّر Fragment مثيل View صالحًا. في معظم الحالات، يمكنك استخدام الإنشاءات الإنشائية للأجزاء التي تأخذ @LayoutId، والتي تعمل على تضخيم طبقة العرض تلقائيًا في الوقت المناسب. يمكنك أيضًا إلغاء onCreateView() لتكبير عرض الجزء أو إنشاؤه آليًا.

إذا تم إنشاء مثيل لعرض الجزء باستخدام علامة View غير فارغة، يتم ضبط View على الكسر ويمكن استرداده باستخدام getView(). بعد ذلك، يتم تعديل getViewLifecycleOwnerLiveData() لإضافة العنصر الجديد INITIALIZED LifecycleOwner المتوافق مع عرض الجزء. يُطلق على استدعاء دورة حياة onViewCreated() أيضًا في هذا الوقت.

هذا هو المكان المناسب لإعداد الحالة الأولية لعرضك، لبدء مراقبة مثيلات LiveData التي تعدِّل استدعاءاتها عرض الجزء، وإعداد المعدِّلات على أي مثيلات RecyclerView أو ViewPager2 في عرض الجزء.

تم إنشاء جزء وعرض

بعد إنشاء عرض الجزء، تتم استعادة حالة العرض السابقة، إن توفّرت، ويتم نقل Lifecycle للعرض إلى الحالة CREATED. يرسل مالك دورة حياة العرض أيضًا حدث ON_CREATE إلى المراقبين. هنا يجب عليك استعادة أي حالة إضافية مرتبطة بعرض الجزء.

تؤدي عملية النقل هذه أيضًا إلى استدعاء onViewStateRestored().

بدء التجزئة والعرض

ننصح بشدة بربط المكوّنات التي تستنِد إلى دورة الحياة بحالة STARTED للجزء، لأنّ هذه الحالة تضمن إتاحة عرض الجزء، في حال تم إنشاؤه، وأنّه من الآمن إجراء FragmentTransaction على العنصر FragmentManager الثانوي للجزء. إذا لم يكن عرض الجزء فارغًا، سيتم نقل عرض الجزء Lifecycle إلى STARTED مباشرةً بعد نقل Lifecycle للجزء إلى STARTED.

عندما يصبح الجزء STARTED، يتم استدعاء استدعاء onStart().

تم استئناف الجزء والعرض

عند ظهور الجزء، تكون جميع تأثيرات Animator وTransition قد انتهت، ويصبح الجزء جاهزًا لتفاعل المستخدم. يتم نقل Lifecycle للجزء إلى الحالة RESUMED، ويتم استدعاء استدعاء onResume().

إنّ الانتقال إلى RESUMED هو إشارة مناسبة للإشارة إلى أنّ المستخدم يستطيع الآن التفاعل مع الجزء. أمّا بالنسبة إلى الأجزاء التي لا تمثّل RESUMED، فيجب عدم ضبط التركيز يدويًا على طرق العرض أو محاولة التعامل مع إمكانية رؤية أسلوب الإدخال.

انتقالات الحالة لأسفل

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

بدء التجزئة والعرض

عندما يبدأ المستخدم في مغادرة الكسر، ويبقى الكسر ظاهرًا، تتم إعادة ضبط Lifecycle للجزء ولعرضه إلى حالة STARTED وإرسال حدث ON_PAUSE إلى المراقبين. بعد ذلك، يستدعي الجزء استدعاء onPause() الخاص به.

تم إنشاء جزء وعرض

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

كما هو موضّح في الشكل 2، يختلف ترتيب معاودة الاتصال في onStop() وحفظ الحالة باستخدام onSaveInstanceState() بناءً على مستوى واجهة برمجة التطبيقات. بالنسبة إلى جميع مستويات واجهة برمجة التطبيقات التي تسبق الإصدار 28 من واجهة برمجة التطبيقات، يتم استدعاء onSaveInstanceState() قبل onStop(). بالنسبة إلى مستويات واجهة برمجة التطبيقات رقم 28 والمستويات الأعلى، يتم عكس ترتيب الاستدعاء.

استدعاء اختلافات الطلب لـ onStop() وonSaveInstanceState()
الشكل 2. طلب معرفة الاختلافات في الترتيب لكل من onStop() و onSaveInstanceState().

تم إنشاء الجزء وعرض دمره

بعد اكتمال جميع عمليات الرسوم المتحركة وعمليات الانتقال للخروج، وفصل عرض الجزء من النافذة، يتم نقل عرض الجزء Lifecycle إلى حالة DESTROYED ويتم إرسال حدث ON_DESTROY إلى المراقبين. بعد ذلك، يستدعي الجزء معاودة الاتصال بـ onDestroyView(). في هذه المرحلة، قد وصل عرض الجزء إلى نهاية مراحل نشاطه، ويعرض getViewLifecycleOwnerLiveData() قيمة null.

عند هذه المرحلة، يجب إزالة جميع الإشارات إلى عرض الجزء، ما يؤدي إلى تجميع بيانات غير صحيحة في عرض الجزء.

تم تدمير الجزء

وفي حال إزالة الجزء أو تلف FragmentManager، يتم نقل Lifecycle الخاص بالجزء إلى حالة DESTROYED وإرسال حدث ON_DESTROY إلى المراقبين. بعد ذلك، يستدعي الجزء معاودة الاتصال بـ onDestroy(). في هذه المرحلة، وصل الجزء إلى نهاية دورة حياته.

مراجع إضافية

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

الأدلّة

المدوّنات