OOZOU
تواصلوا معنا
العودة إلى المدونة

بناء RecyclerView متداخل في Android باستخدام ConcatAdapter

يتيح MergeAdapter دمج عدة adapters بالتتابع لعرضها داخل RecyclerView واحد.

19 يونيو 2020
9 دقائق للقراءة
بناء RecyclerView متداخل في Android باستخدام ConcatAdapter

مع ازدياد تعقيد واجهات التطبيقات، سيأتي وقت تحتاجون فيه إلى التعامل مع RecyclerView داخل RecyclerView آخر. ومن الأمثلة الجيدة على هذا النوع من الواجهات تطبيق Klook. والأرجح أنهم بنوا هذه الواجهة باستخدام RecyclerView متداخل. وإحدى طرق تحقيق ذلك أن نبني RecyclerView بهذا الشكل. وفي هذا المثال سنوضح كيفية إعداد RecyclerView المتداخل. هكذا أنشئ الـ Adapter الخارجي الذي يتحكم في محتوى RecyclerView المتداخل. يحتوي كل Viewholder على عنوان وقائمة. وقد تبدو الفكرة العامة لكود الـ Adapter الخارجي على النحو التالي:

class OutAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CheckUpResultViewHolder {
        return when (viewType) {
            R.<em>layout</em>.<em>layout_header </em>-> HeaderViewHolder(parent)
            R.<em>layout</em>.<em>layout_first_section </em>-> FirstSectionViewHolder(parent)
            R.<em>layout</em>.<em>layout_second_section </em>-> SecondSectionViewHolder(parent)
            R.<em>layout</em>.<em>layout_third_section </em>-> ThirdSectionViewHolder(parent)
        }
    }

    override fun getItemCount(): Int {
        return 6
    }

    override fun onBindViewHolder(holder: CheckUpResultViewHolder, position: Int) {
        //binding data
    }

    override fun getItemViewType(position: Int): Int = when (position) {
        0, 2, 4 -> R.<em>layout</em>.<em>layout_header
        </em>1 -> R.<em>layout</em>.<em>layout_first_section
        </em>3 -> R.<em>layout</em>.<em>layout_second_section
        </em>5 -> R.<em>layout</em>.<em>layout_third_section
    </em>}
}
//kotlin-language

تحديث: غيّرت Google اسم MergeAdapter إلى ConcatAdapter. لننتقل الآن إلى MergeAdapter. وهو صنف (class) متاح منذ الإصدار recyclerview:1.2.0-alpha02.

يساعد MergeAdapter على دمج عدة adapters بالتتابع لعرضها في RecyclerView واحد دون الحاجة إلى إنشاء adapter إضافي. وفي حالتنا، إذا استخدمنا MergeAdapter فلن نحتاج إلى إنشاء الـ Adapter الخارجي أصلًا. ويمكننا بناء RecyclerView المتداخل بهذا الشكل.

كما ترون، فصلنا كل قسم من أقسام الواجهة في adapter مستقل. ويساعدنا MergeAdapter على حصر منطق كل قسم في adapter واحد، مما يسهّل إعادة استخدامه. ثم ندمج الـ adapters كما في المقتطف التالي:

val mergeAdapter = MergeAdapter(
    firstHeaderAdapter, 
    firstAdapter, 
    secondHeaderAdapter,
    secondAdapter,
    thirdHeaderAdapter,
    thirdAdapter
)
recyclerView.adapter = mergeAdapter

يمكن أن تكون adapters العناوين الثلاثة نسخًا (instances) مختلفة من صنف Header adapter نفسه. وداخل Header adapter تكون قيمة getItemCount دائمًا واحدًا، ويمكننا استخدام View Type للتحكم في حالة تخطيط العنوان. أما بقية الـ adapters فهي مثل أي RecyclerView Adapter معتاد. فكيف يسهّل MergeAdapter عملنا؟

  1. لا حاجة إلى Adapter إضافي لـ RecyclerView الخارجي.
  2. يتيح لكم MergeAdapter تغليف (encapsulate) كل adapter على حدة بدلًا من جمع مصادر البيانات والمنطق في adapter واحد. ولتوضيح ذلك، لننظر في السيناريو التالي: لنفترض أن عنوان كل قسم في RecyclerView المتداخل يجب أن يعرض حالة التحميل.

من دون MergeAdapter، يجب أن يوجد منطق إظهار حالة التحميل وإخفائها في الـ Adapter الخارجي. ووضع منطق العنوان ومنطق القائمة في adapter واحد ليس من أفضل الممارسات، لأننا قد لا نتمكن من إعادة استخدام هذا المنطق في مكان آخر. لذلك من الأفضل أن نفصل كل قسم في adapter خاص به. ومع MergeAdapter يمكننا دمج الأقسام بسهولة في RecyclerView واحد. ويغلّف كل adapter منطقه الخاص، مما يجعله قابلًا لإعادة الاستخدام.

مقدمة عن ConcatAdapter في Android

ConcatAdapter أداة قوية في Android تتيح للمطورين دمج عدة adapters في adapter واحد، مما يسهّل إدارة تخطيطات الواجهة المعقدة. وتبرز فائدتها خصوصًا مع RecyclerView، إذ تتيح تغليفًا أفضل للـ adapters وإعادة استخدامها. وباستخدام ConcatAdapter يستطيع المطورون التركيز على تصميم الواجهة وتجربة المستخدم بدلًا من الانشغال بتفاصيل التنفيذ. وهذا النهج لا يبسّط عملية التطوير فحسب، بل يجعل قاعدة الكود أسهل في الصيانة أيضًا.

فهم الـ Adapter

الـ Adapter مكوّن أساسي في Android يعمل جسرًا بين البيانات والواجهة. فهو مسؤول عن تزويد RecyclerView بالبيانات وربطها بالـ views. وفي سياق ConcatAdapter، يمكن النظر إلى الـ adapter بوصفه وحدة بيانات مستقلة يجب عرضها في RecyclerView. ومن خلال دمج عدة adapters، يتيح ConcatAdapter للمطورين بناء تخطيطات واجهة معقدة بسهولة. ويتولى كل adapter نوعًا محددًا من البيانات، فيبقى المنطق مقسّمًا إلى وحدات يسهل إدارتها. وهذا الفصل بين المسؤوليات أساسي لبناء تطبيقات قابلة للتوسّع وسهلة الصيانة.

إعداد ConcatAdapter

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

ملاحظات إضافية

  • إذا احتاجت عدة adapters داخل MergeAdapter إلى إعادة استخدام صنف ViewHolder نفسه، فهناك إعداد إضافي بسيط. علينا ضبط isolateViewTypes على false.
val builder = MergeAdapter.Config.Builder()
builder.setIsolateViewTypes(<strong>false</strong>)

val mergeAdapter = MergeAdapter(
    builder.build(),
    firstHeaderAdapter, 
    firstAdapter, 
    secondHeaderAdapter,
    secondAdapter,
    thirdHeaderAdapter,
    thirdAdapter
)
  • يمكن إضافة الـ adapters داخل MergeAdapter أو إزالتها ديناميكيًا بهذه الطريقة.
mergeAdapter.addAdapter(6,fourtAdapter)

mergeAdapter.removeAdapter(//adapter)
  • تجنبوا استدعاء notifyDataSetChanged في الـ adapters الداخلية، لأن MergeAdapter سيستدعي notifyDataSetChanged هو الآخر. لذلك يُفضَّل استخدام notifyItemRangeChanged وnotifyItemInserted وnotifyItemChange وما شابهها**.**

مزايا استخدام ConcatAdapter في Android مع RecyclerView المتداخل

مع أن المقال يغطي أساسيات استخدام ConcatAdapter، فمن المفيد التوسع في المزايا الرئيسية لهذا النهج:الفصل بين المسؤوليات:

  • كل adapter مسؤول عن نوع واحد من البيانات، مما يجعل الكود معياريًا وأسهل في الصيانة.
  • على سبيل المثال، يمكن أن يكون لديكم adapter للعنوان، وآخر للمحتوى، وثالث للتذييل.

إعادة الاستخدام:

  • يمكن إعادة استخدام كل adapter في شاشات مختلفة أو في RecyclerView أخرى داخل تطبيقكم، مما يقلل التكرار ويحسّن الاتساق.
  • ويفيد هذا بشكل خاص إذا أردتم الحفاظ على مظهر وتجربة متسقين في أجزاء التطبيق المختلفة.

الأداء:

  • بفضل التعامل مع كل adapter على حدة، يحسّن ConcatAdapter عمليات RecyclerView مثل الربط (binding) والمقارنة (diffing) وإعادة تدوير الـ views.

المحتوى الديناميكي:

  • أضيفوا الأقسام إلى RecyclerView أو أزيلوها بسهولة عبر إلحاق الـ adapters أو فصلها ديناميكيًا.

التعامل مع أحداث النقر في RecyclerView المتداخل

عند العمل مع RecyclerView متداخل، قد يكون التعامل مع أحداث النقر صعبًا أحيانًا بسبب البنية متعددة الطبقات. وإليكم بعض النصائح:

  1. فوّضوا النقرات إلى العنصر الأب:

    مرّروا click listener من adapter الخاص بـ RecyclerView الأب إلى RecyclerView المتداخل. وهكذا تنتقل أحداث النقر إلى الأعلى وتُعالَج في مكان مركزي واحد، وهذا ضروري إذا أردتم قاعدة كود نظيفة يسهل التحكم فيها.

  2. استخدموا الواجهات (Interfaces):

    عرّفوا interface للتعامل مع النقرات ونفّذوها في الـ activity أو الـ fragment الأب، ثم مرّروا هذه الـ interface إلى adapter الخاص بـ RecyclerView المتداخل.

  3. استخدموا ViewModel:

    في التطبيقات التي تتبع معمارية MVVM، اربطوا أحداث النقر بـ ViewModel مشترك. وهذا يمنع الاقتران الوثيق بين الـ adapters والواجهة.

التحديات الشائعة وحلولها

  1. أداء التمرير في RecyclerView - المشكلة: عند عرض عدة RecyclerView متداخلة، قد يتراجع أداء التمرير.
    • الحل:استخدموا setHasFixedSize(true) لكل من RecyclerView الأب والابن، وعطّلوا التمرير المتداخل في RecyclerView الابن باستخدام setNestedScrollingEnabled(false). وهذا يضمن إدارة أنواع الـ views بكفاءة ويخفف العبء عن RecyclerView.
  2. تحديث البيانات ديناميكيًا - المشكلة: قد تؤدي إضافة الأقسام أو إزالتها ديناميكيًا إلى عدم اتساق في الواجهة.
    • الحل: استخدموا notifyItemRangeInserted() أو notifyItemRangeRemoved() لتحديث الأقسام المتأثرة فقط. فهذه الطريقة تحصر التحديث في الأقسام المعنية، مما يجعل عرض البيانات الجديدة أكثر كفاءة. ويمكنكم بدلًا من ذلك استخدام DiffUtil لإدارة تغييرات البيانات بكفاءة.
  3. الالتباس في مواضع البيانات - المشكلة: قد يكون تحديد الموضع الصحيح للبيانات في RecyclerView المتداخل أمرًا معقدًا.
    • الحل: خزّنوا موضع RecyclerView الأب كوسم (tag) في ViewHolder الخاص بـ RecyclerView المتداخل، واستخدموا هذا الموضع لربط البيانات بشكل صحيح.

عرض حالة التحميل والعناوين والتذييلات

من أكثر استخدامات ConcatAdapter شيوعًا عرض حالة التحميل والعناوين والتذييلات في RecyclerView. فباستخدام ConcatAdapter يمكنكم إنشاء adapter واحد يعرض حالة التحميل والعناوين والتذييلات إلى جانب البيانات الرئيسية. وهذا يسهّل إدارة الواجهة ويقدّم تجربة مستخدم أفضل. فمثلًا، يمكن أن يكون لديكم adapter للعنوان يعرض مؤشر تحميل أثناء جلب البيانات، وadapter للتذييل يعرض معلومات أو إجراءات إضافية. وبهذا يكون RecyclerView عمليًا وسهل الاستخدام وجذابًا بصريًا في الوقت نفسه.

استخدامات متقدمة لـ ConcatAdapter

1. بناء النماذج الديناميكية

  • استخدموا ConcatAdapter لإنشاء نماذج ديناميكية بأقسام متعددة، مثل حقول الإدخال والقوائم المنسدلة وأقسام الملخص.
  • يمكن أن يكون لكل قسم adapter خاص به، مما يسهّل تعديل الأقسام أو إعادة ترتيبها.

2. كتالوجات التجارة الإلكترونية

  • ابنوا كتالوجات للتجارة الإلكترونية بأقسام مثل "منتجات مميزة" و"الأكثر رواجًا" و"شوهدت مؤخرًا". يمكن أن يكون لكل قسم adapter خاص به، ثم تُدمج جميعها بسلاسة باستخدام ConcatAdapter.

3. قوائم الوسائط المتعددة وأنواع الـ View

  • نفّذوا تخطيطات وسائط متعددة بأقسام للفيديوهات والصور والمقالات. ويتيح لكم ConcatAdapter تبديل هذه الأقسام أو إعادة ترتيبها بسهولة.

نصائح لتصحيح أخطاء RecyclerView المتداخل

  1. سجّلوا مواضع الـ Adapter:
    • سجّلوا مواضع الـ adapters في السجلات (logs) لتتبع السلوكيات غير المتوقعة، خاصة عند تحديث البيانات ديناميكيًا.
  2. تحققوا من الـ Layout Managers:
    • تأكدوا من أن كل RecyclerView (الأب والابن) يستخدم الـ LayoutManager الصحيح.
  3. حلّلوا الأداء:
    • استخدموا أداة profiler في Android Studio لتحديد مواضع الاختناق في التمرير أو تحديث البيانات.
  4. اكتبوا اختبارات وحدة للـ Adapters:
    • اكتبوا unit tests للتحقق من أن كل adapter يتعامل مع البيانات بشكل صحيح، خاصة عند تفاعله مع ConcatAdapter.

خلاصة

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

Related Articles

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

تصميم البرمجيات عملية ممتعة لكنها معقدة، تتطلب الإبداع والتفكير المنطقي ومهارات حل المشكلات.

اقرأوا المزيد
مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

يتطور المشهد الرقمي بسرعة، وعلى الشركات أن تتكيّف لتواكب الطلب المتزايد على السرعة والكفاءة والمعالجة في الوقت الفعلي.

اقرأوا المزيد
مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

يتطور قطاع التجزئة بوتيرة غير مسبوقة بفضل الذكاء الاصطناعي (AI) والواقع المعزّز (AR) وتقنيات التحوّل الرقمي. فلم تعد المتاجر التقليدية مجرد أماكن لبيع المنتجات، بل أصبحت متاجر ذكية وتفاعلية.

اقرأوا المزيد

Have a Project in Mind?

Let's discuss how we can help bring your ideas to life with our expertise in web and mobile development.

ابدأوا المحادثةhello@oozou.com
OOZOU Logo

بانكوك · سنغافورة · هونغ كونغ

X
Facebook
Instagram
LinkedIn
OOZOU Co., Ltd.
548 One City Centre
Ploenchit Road
Bangkok 10330
Thailand
+66 2544 0000
hello@oozou.com

الخدمات

  • تطوير الويب
  • وكلاء الذكاء الاصطناعي والذكاء الاصطناعي التوليدي
  • تطوير تطبيقات الجوال
  • تحليلات البيانات وهندستها
  • تصميم تجربة المستخدم وواجهته (UX/UI) وتصميم المنتجات
  • التحوّل الرقمي

الشركة

  • من نحن
  • الوظائف
  • المدونة
  • دراسات الحالة
  • عروض حية
  • تعلّمت اليوم
  • تواصل معنا

المزيد

  • القطاعات
  • شبكة الشركاء
© 2026 OOZOU. جميع الحقوق محفوظة.
سياسة الخصوصيةمدونة قواعد السلوكسياسة مكافحة الرشوة والفساد