الـ Fragments
الـ Fragments
مع نمو تطبيق Android الخاص بك إلى ما هو أبعد من شاشة واحدة، تكتشف سريعًا أن استخدام Activity واحدة لكل شاشة أمر خشن للغاية. تحتاج الأجهزة اللوحية إلى عرض قائمة رئيسية بجانب لوحة تفاصيل في آنٍ واحد، في حين تعرض الهواتف كلًّا منهما بالتتابع. إن تكرار منطق التخطيط داخل Activity منفصلتين أمر غير قابل للصيانة. حلّ Android هذه المشكلة عبر Fragment — وهو قطعة مستقلة وقابلة لإعادة الاستخدام من واجهة المستخدم والسلوك تعيش داخل Activity لكنها تدير عرضها الخاص ودورة حياتها الخاصة.
ما هو الـ Fragment
Fragment هو فئة في androidx.fragment.app تمثّل جزءًا من واجهة المستخدم أو السلوك داخل Activity. فكّر فيه كشاشة فرعية معيارية: لديه ملف XML خاص بتخطيطه، وفئة Java خاصة به، ودورة حياة خاصة تعمل متداخلة داخل دورة حياة Activity المضيفة. يمكن لـ Activity واحدة استضافة عدة Fragments، وتبديلها ذهابًا وإيابًا، وحتى إعادة استخدام نفس فئة Fragment في عدة Activities.
إنشاء Fragment
تُجاوز فئة Fragment الدالة onCreateView() لنفخ تخطيطها، وتختياريًا onViewCreated() لإعداد العروض بعد النفخ. يجب أن لا تبحث عن عروض أو تضبط مستمعات في المنشئ — إذ لا يوجد العرض بعد وقت الإنشاء.
ملف التخطيط المقابل res/layout/fragment_profile.xml هو ملف XML عادي للتخطيط بعنصر جذر — مثل ConstraintLayout — تمامًا كما تكتبه لـ Activity.
إضافة Fragment إلى Activity
تُدار الـ Fragments عبر FragmentManager. يمكنك إما تعريف Fragment بشكل ثابت في ملف XML الخاص بتخطيط Activity، أو إضافته ديناميكيًا أثناء التشغيل عبر FragmentTransaction. النهج الديناميكي هو ما ستحتاجه دائمًا تقريبًا لأنه يتيح لك استبدال الـ Fragments وتحريكها.
التعريف الثابت (XML للتخطيط) — الأبسط، لكن لا يمكن استبداله أثناء التشغيل:
المعاملة الديناميكية (Java) — النهج المرن:
savedInstanceState == null. عند دوران الجهاز، يُعيد Android إنشاء Activity ويستعيد تلقائيًا أي Fragments كانت مُضافة للمكدس. إن أضفت الـ Fragment مجددًا دون هذا الشرط، ستنتهي بنسخ مكررة من الـ Fragment مُكدّسة فوق بعضها.
دورة حياة الـ Fragment
تعمل دورة حياة Fragment إلى جانب دورة حياة Activity المضيفة، لكنها تحتوي على استدعاءات راجعة إضافية خاصة بعلاقتها مع Activity وعرضها الخاص:
onAttach(context)— ارتبط الـ Fragment بالـ Activity. السياقContextمتاح الآن.onCreate(savedInstanceState)— أُنشئ الـ Fragment. هنا تُهيّئ الحالة غير المرئية (ViewModels، المعطيات).onCreateView()— انفخ وأعد هرمية عرض الـ Fragment.onViewCreated(view, savedInstanceState)— العرض جاهز. اضبط المستمعات، راقب LiveData، واملأ واجهة المستخدم هنا.onStart()— أصبح الـ Fragment مرئيًا.onResume()— الـ Fragment في المقدمة وتفاعلي.onPause()— فقد الـ Fragment التركيز (جاء Fragment أو Activity آخر إلى المقدمة).onStop()— لم يعد الـ Fragment مرئيًا.onDestroyView()— يجري تدمير هرمية العرض. أطلق أي مراجع للعروض هنا لتجنب تسرّب الذاكرة.onDestroy()— يُدمَّر الـ Fragment نفسه.onDetach()— فُصل الـ Fragment عن الـ Activity.
onDestroyView(). يُسهّل ViewBinding ذلك بنمط: binding = null; في onDestroyView().
معطيات الـ Fragment — نمط newInstance
لا تمرّر البيانات إلى Fragment أبدًا عبر منشئ بمعاملات. سيُعيد Android إنشاء الـ Fragment عبر منشئه الافتراضي عند استعادة الحالة، مما يُفقد أي معطيات مُمرَّرة عبر المنشئ. النهج الصحيح هو نمط المصنع newInstance: احزم البيانات في Bundle وأرفقها عبر setArguments().
في موضع الاستدعاء داخل Activity:
replace() مع addToBackStack() عند التنقل للأمام. replace() يستبدل الـ Fragment الحالي؛ وaddToBackStack() يضمن أن زر الرجوع يعكس المعاملة ويعيد الـ Fragment السابق، مانحًا المستخدمين تجربة التنقل التي يتوقعونها.
متى تستخدم الـ Fragments
- تخطيطات متعددة الأجزاء: عرض القائمة والتفاصيل جنبًا إلى جنب على الأجهزة اللوحية؛ جزء واحد في كل مرة على الهواتف.
- تنقل بالتبويبات: كل تبويب هو Fragment داخل
ViewPager2أو شريط التنقل السفلي. - أقسام واجهة مستخدم قابلة لإعادة الاستخدام: شريط أدوات مشترك، أو عرض خريطة، أو قسم تعليقات يظهر على شاشات متعددة.
- Jetpack Navigation: يُدير مكوّن Navigation تطبيقًا بـ Activity واحدة حيث تكون كل شاشة وجهة Fragment — وهذا هو النهج المعماري الحديث الموصى به.
الخلاصة
الـ Fragment هو مكوّن واجهة مستخدم معياري وقابل لإعادة الاستخدام يعيش داخل Activity. لديه دورة حياة خاصة (onCreateView وonViewCreated وonDestroyView هي أهم الاستدعاءات الراجعة لأعمال واجهة المستخدم)، وتخطيطه الخاص، وحالته الخاصة. تُمرَّر البيانات عبر نمط bundle في newInstance لا عبر معطيات المنشئ. معاملات Fragment — add وreplace وaddToBackStack — هي الآلية التي تُؤلّف بها Activity عدة Fragments وتتنقل بينها. في الدرس القادم ستستخدم مكوّن Jetpack Navigation الذي يبني على الـ Fragments لمنحك رسم بياني كامل للتنقل بين الشاشات.