‫Android Kotlin Fundamentals 07.5: العناوين في RecyclerView

هذا الدرس التطبيقي حول الترميز هو جزء من دورة "أساسيات Android Kotlin". يمكنك تحقيق أقصى استفادة من هذه الدورة التدريبية إذا اتبعت ترتيب الخطوات في دروس البرمجة. يتم إدراج جميع الدروس التطبيقية حول الترميز الخاصة بالدورة التدريبية في الصفحة المقصودة للدروس التطبيقية حول الترميز في دورة Android Kotlin Fundamentals.

مقدمة

في هذا الدرس العملي، ستتعرّف على كيفية إضافة عنوان يمتد على عرض القائمة المعروضة في RecyclerView. تستند هذه السلسلة إلى تطبيق Sleep Tracker من سلسلة الدروس البرمجية السابقة.

ما يجب معرفته

  • كيفية إنشاء واجهة مستخدم أساسية باستخدام نشاط ولقطات وطرق عرض
  • كيفية التنقّل بين الأجزاء وكيفية استخدام safeArgs لنقل البيانات بين الأجزاء
  • عرض النماذج وعوامل إنشاء النماذج وعمليات التحويل وLiveData والمراقبين المرتبطين بها
  • كيفية إنشاء قاعدة بيانات Room وإنشاء كائن وصول إلى البيانات (DAO) وتحديد الكيانات
  • كيفية استخدام الروتينات الفرعية للتفاعلات مع قاعدة البيانات والمهام الأخرى التي تستغرق وقتًا طويلاً
  • كيفية تنفيذ RecyclerView أساسي باستخدام Adapter وViewHolder وتنسيق العناصر
  • كيفية تنفيذ ربط البيانات في RecyclerView
  • كيفية إنشاء واستخدام أدوات ربط البيانات لتحويل البيانات
  • كيفية استخدام GridLayoutManager
  • كيفية تسجيل النقرات على العناصر في RecyclerView. والتعامل معها

أهداف الدورة التعليمية

  • كيفية استخدام أكثر من ViewHolder مع RecyclerView لإضافة عناصر بتنسيق مختلف على وجه التحديد، كيفية استخدام ViewHolder ثانٍ لإضافة عنوان فوق العناصر المعروضة في RecyclerView

الإجراءات التي ستنفذّها

  • يمكنك الاستناد إلى تطبيق TrackMySleepQuality من الدرس التطبيقي السابق في هذه السلسلة.
  • أضِف عنوانًا يمتد على عرض الشاشة فوق ليالي النوم المعروضة في RecyclerView.

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

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

يستخدم هذا التطبيق بنية مبسطة تتضمّن وحدة تحكّم في واجهة المستخدم ونموذج عرض وLiveData وقاعدة بيانات Room لتخزين بيانات النوم بشكل دائم.

في هذا الدرس العملي، ستضيف عنوانًا إلى شبكة العناصر المعروضة. ستبدو شاشتك الرئيسية النهائية على النحو التالي:

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

لا تعرف RecyclerView أي معلومات عن بياناتك أو نوع التنسيق الذي يتضمّنه كل عنصر. تعمل LayoutManager على ترتيب العناصر على الشاشة، ولكنّ المحوّل يكيّف البيانات ليتم عرضها ويمرّر عناصر الحاوية إلى RecyclerView. لذا، ستضيف الرمز لإنشاء العناوين في المحوّل.

طريقتان لإضافة العناوين

في RecyclerView، يتوافق كل عنصر في القائمة مع رقم فهرس يبدأ من 0. على سبيل المثال:

[البيانات الفعلية] -> [طرق عرض المحوّل]

[0: SleepNight] -> [0: SleepNight]

[1: SleepNight] -> [1: SleepNight]

[2: SleepNight] -> [2: SleepNight]

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

[البيانات الفعلية] -> [طرق عرض المحوّل]

[0: Header]

[0: SleepNight] -> [1: SleepNight]

[1: SleepNight] -> [2: SleepNight]

[2: SleepNight] -> [3: SleepNight.

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

[البيانات الفعلية] -> [طرق عرض المحوّل]

[0: Header] -> [0: Header]

[1: SleepNight] -> [1: SleepNight]

[2: SleepNight] -> [2: SleepNight]

[3: SleepNight] -> [3: SleepNight]

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

في هذا الدرس العملي، ستعدّل RecyclerView لعرض عنوان في بداية القائمة. في هذه الحالة، سيستخدم تطبيقك ViewHolder مختلفًا للعنوان عن ViewHolder عناصر البيانات. سيتحقّق التطبيق من فهرس القائمة لتحديد ViewHolder الذي سيتم استخدامه.

الخطوة 1: إنشاء فئة DataItem

لتجريد نوع العنصر والسماح للمحوّل بالتعامل مع "العناصر" فقط، يمكنك إنشاء فئة حامل بيانات تمثّل إما SleepNight أو Header. ستكون مجموعة البيانات بعد ذلك عبارة عن قائمة بعناصر حامل البيانات.

يمكنك الحصول على تطبيق المبتدئين من GitHub أو مواصلة استخدام تطبيق SleepTracker الذي أنشأته في الدرس العملي السابق.

  1. نزِّل الرمز RecyclerViewHeaders-Starter من GitHub. يحتوي الدليل RecyclerViewHeaders-Starter على الإصدار الأولي من تطبيق SleepTracker اللازم لهذا الدرس البرمجي. يمكنك أيضًا مواصلة العمل على تطبيقك المكتمل من الدرس العملي السابق إذا أردت ذلك.
  2. افتح الملف SleepNightAdapter.kt.
  3. أسفل فئة SleepNightListener، في المستوى الأعلى، حدِّد فئة sealed باسم DataItem تمثّل عنصر بيانات.

    يحدّد الصف sealed نوعًا مغلقًا، ما يعني أنّه يجب تحديد جميع الفئات الفرعية من DataItem في هذا الملف. نتيجةً لذلك، يعرف المترجم عدد الفئات الفرعية. لا يمكن لجزء آخر من الرمز تحديد نوع جديد من DataItem قد يؤدي إلى تعطُّل المحوّل البرمجي.
sealed class DataItem {

 }
  1. داخل نص الفئة DataItem، حدِّد فئتين تمثّلان الأنواع المختلفة من عناصر البيانات. الأول هو SleepNightItem، وهو عبارة عن غلاف حول SleepNight، لذا يأخذ قيمة واحدة تُسمى sleepNight. لجعلها جزءًا من الفئة المحكمة، يجب أن توسّع DataItem.
data class SleepNightItem(val sleepNight: SleepNight): DataItem()
  1. الفئة الثانية هي Header، لتمثيل عنوان. بما أنّ العنوان لا يتضمّن أي بيانات فعلية، يمكنك تعريفه على أنّه object. وهذا يعني أنّه لن يكون هناك سوى مثيل واحد من Header. كرِّر الخطوة السابقة لتمديد DataItem.
object Header: DataItem()
  1. داخل DataItem، على مستوى الفئة، حدِّد السمة abstract Long باسم id. عندما يستخدم المحوّل البرمجي DiffUtil لتحديد ما إذا كان قد تم تغيير عنصر وكيفية تغييره، يجب أن يعرف DiffItemCallback معرّف كل عنصر. سيظهر لك خطأ لأنّ SleepNightItem وHeader يجب أن تتجاوزا السمة المجردة id.
abstract val id: Long
  1. في SleepNightItem، استبدِل id لعرض nightId.
override val id = sleepNight.nightId
  1. في Header، استبدِل id لعرض Long.MIN_VALUE، وهو عدد صغير جدًا (أي ‎-2 أس 63). وبالتالي، لن يتعارض هذا المعرّف أبدًا مع أي nightId حالي.
override val id = Long.MIN_VALUE
  1. يجب أن يبدو الرمز البرمجي المكتمل على النحو التالي، ويجب أن يتم إنشاء تطبيقك بدون أخطاء.
sealed class DataItem {
    abstract val id: Long
    data class SleepNightItem(val sleepNight: SleepNight): DataItem()      {
        override val id = sleepNight.nightId
    }

    object Header: DataItem() {
        override val id = Long.MIN_VALUE
    }
}

الخطوة 2: إنشاء ViewHolder للعنوان

  1. أنشئ التصميم للعنوان في ملف جديد لمورد التصميم باسم header.xml يعرض TextView. لا يوجد أي شيء مثير للاهتمام في هذا، لذا إليك الرمز.
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:text="Sleep Results"
    android:padding="8dp" />
  1. استخرِج "Sleep Results" إلى مورد سلسلة وسمِّه header_text.
<string name="header_text">Sleep Results</string>
  1. في ملف SleepNightAdapter.kt، داخل SleepNightAdapter، فوق الفئة ViewHolder، أنشئ فئة TextViewHolder جديدة. تعمل هذه الفئة على تضخيم تنسيق textview.xml، وتعرض مثيلاً من TextViewHolder. بما أنّك أجريت ذلك من قبل، إليك الرمز، وعليك استيراد View وR:
    class TextViewHolder(view: View): RecyclerView.ViewHolder(view) {
        companion object {
            fun from(parent: ViewGroup): TextViewHolder {
                val layoutInflater = LayoutInflater.from(parent.context)
                val view = layoutInflater.inflate(R.layout.header, parent, false)
                return TextViewHolder(view)
            }
        }
    }

الخطوة 3: تعديل SleepNightAdapter

بعد ذلك، عليك تعديل بيان SleepNightAdapter. بدلاً من دعم نوع واحد فقط من ViewHolder، يجب أن يكون قادرًا على استخدام أي نوع من عناصر العرض.

تحديد أنواع العناصر

  1. في SleepNightAdapter.kt، على المستوى الأعلى، أسفل عبارات import وفوق SleepNightAdapter، حدِّد ثابتَين لأنواع العرض.

    يجب أن يميّز RecyclerView نوع عرض كل عنصر، حتى يتمكّن من تعيين عنصر نائب للعرض بشكل صحيح.
    private val ITEM_VIEW_TYPE_HEADER = 0
    private val ITEM_VIEW_TYPE_ITEM = 1
  1. داخل SleepNightAdapter، أنشئ دالة لتجاوز getItemViewType() لعرض العنوان أو الثابت الصحيح للعنصر استنادًا إلى نوع العنصر الحالي.
override fun getItemViewType(position: Int): Int {
        return when (getItem(position)) {
            is DataItem.Header -> ITEM_VIEW_TYPE_HEADER
            is DataItem.SleepNightItem -> ITEM_VIEW_TYPE_ITEM
        }
    }

تعديل تعريف SleepNightAdapter

  1. في تعريف SleepNightAdapter، عدِّل الوسيطة الأولى لـ ListAdapter من SleepNight إلى DataItem.
  2. في تعريف SleepNightAdapter، غيِّر الوسيط العام الثاني لـ ListAdapter من SleepNightAdapter.ViewHolder إلى RecyclerView.ViewHolder. ستظهر لك بعض الأخطاء بشأن التعديلات الضرورية، ويجب أن يبدو عنوان الصف كما هو موضّح أدناه.
class SleepNightAdapter(val clickListener: SleepNightListener):
       ListAdapter<DataItem, RecyclerView.ViewHolder>(SleepNightDiffCallback()) {

تعديل طريقة onCreateViewHolder()

  1. غيِّر توقيع onCreateViewHolder() لعرض RecyclerView.ViewHolder.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder
  1. وسِّع نطاق تنفيذ طريقة onCreateViewHolder() لاختبار عنصر العرض المناسب وإرجاعه لكل نوع من أنواع العناصر. يجب أن تبدو الطريقة المعدَّلة مثل الرمز البرمجي أدناه.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            ITEM_VIEW_TYPE_HEADER -> TextViewHolder.from(parent)
            ITEM_VIEW_TYPE_ITEM -> ViewHolder.from(parent)
            else -> throw ClassCastException("Unknown viewType ${viewType}")
        }
    }

تعديل onBindViewHolder()

  1. غيِّر نوع المَعلمة onBindViewHolder() من ViewHolder إلى RecyclerView.ViewHolder.
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int)
  1. أضِف شرطًا لتعيين البيانات إلى عنصر نائب للعرض فقط إذا كان العنصر النائب ViewHolder.
        when (holder) {
            is ViewHolder -> {...}
  1. تحويل نوع العنصر الذي تعرضه getItem() إلى DataItem.SleepNightItem يجب أن تبدو دالة onBindViewHolder() المكتملة على النحو التالي.
  override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is ViewHolder -> {
                val nightItem = getItem(position) as DataItem.SleepNightItem
                holder.bind(nightItem.sleepNight, clickListener)
            }
        }
    }

تعديل عمليات معاودة الاتصال diffUtil

  1. غيِّر الطرق في SleepNightDiffCallback لاستخدام فئة DataItem الجديدة بدلاً من SleepNight. يمكنك إيقاف تحذير lint كما هو موضّح في الرمز البرمجي أدناه.
class SleepNightDiffCallback : DiffUtil.ItemCallback<DataItem>() {
    override fun areItemsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
        return oldItem.id == newItem.id
    }
    @SuppressLint("DiffUtilEquals")
    override fun areContentsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
        return oldItem == newItem
    }
}

إضافة العنوان وإرساله

  1. داخل SleepNightAdapter، أسفل onCreateViewHolder()، عرِّف الدالة addHeaderAndSubmitList() كما هو موضّح أدناه. تأخذ هذه الدالة قائمة SleepNight. بدلاً من استخدام submitList()، التي توفّرها ListAdapter، لإرسال قائمتك، ستستخدم هذه الدالة لإضافة عنوان ثم إرسال القائمة.
fun addHeaderAndSubmitList(list: List<SleepNight>?) {}
  1. داخل addHeaderAndSubmitList()، إذا كانت القائمة التي تم تمريرها هي null، يتم عرض رأس فقط، وإلا يتم إرفاق الرأس ببداية القائمة، ثم يتم إرسال القائمة.
val items = when (list) {
                null -> listOf(DataItem.Header)
                else -> listOf(DataItem.Header) + list.map { DataItem.SleepNightItem(it) }
            }
submitList(items)
  1. افتح الملف SleepTrackerFragment.kt وغيِّر الاستدعاء إلى submitList() إلى addHeaderAndSubmitList().
  1. شغِّل تطبيقك ولاحظ كيف يتم عرض العنوان كأول عنصر في قائمة عناصر النوم.

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

  • يظهر العنوان في أعلى يمين الصفحة، ولا يمكن تمييزه بسهولة.
  • لا يهم كثيرًا بالنسبة إلى قائمة قصيرة ذات عنوان واحد، ولكن يجب عدم إجراء معالجة القوائم في addHeaderAndSubmitList() على سلسلة التعليمات الرئيسية لواجهة المستخدم. تخيَّل قائمة تحتوي على مئات العناصر وعدة عناوين ومنطقًا لتحديد مكان إدراج العناصر. يجب أن يتم تنفيذ هذا العمل في روتين فرعي.

تغيير addHeaderAndSubmitList() لاستخدام إجراءات فرعية:

  1. في المستوى الأعلى داخل الفئة SleepNightAdapter، حدِّد CoroutineScope باستخدام Dispatchers.Default.
private val adapterScope = CoroutineScope(Dispatchers.Default)
  1. في addHeaderAndSubmitList()، شغِّل روتينًا فرعيًا في adapterScope لتعديل القائمة. بعد ذلك، انتقِل إلى سياق Dispatchers.Main لإرسال القائمة، كما هو موضّح في الرمز أدناه.
 fun addHeaderAndSubmitList(list: List<SleepNight>?) {
        adapterScope.launch {
            val items = when (list) {
                null -> listOf(DataItem.Header)
                else -> listOf(DataItem.Header) + list.map { DataItem.SleepNightItem(it) }
            }
            withContext(Dispatchers.Main) {
                submitList(items)
            }
        }
    }
  1. يجب أن يتم إنشاء الرمز وتشغيله، ولن تلاحظ أي فرق.

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

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

  1. افتح SleepTrackerFragment.kt.
  2. ابحث عن الرمز الذي تحدّد فيه manager، بالقرب من نهاية onCreateView().
val manager = GridLayoutManager(activity, 3)
  1. أسفل manager، حدِّد manager.spanSizeLookup، كما هو موضّح. عليك إنشاء object لأنّ setSpanSizeLookup لا تقبل lambda. لإنشاء object في Kotlin، اكتب object : classname، وفي هذه الحالة GridLayoutManager.SpanSizeLookup.
manager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
}
  1. قد يظهر لك خطأ في المترجم البرمجي لاستدعاء الدالة الإنشائية. إذا كان الأمر كذلك، افتح قائمة النية باستخدام Option+Enter (Mac) أو Alt+Enter (Windows) لتطبيق استدعاء الدالة الإنشائية.
  1. بعد ذلك، سيظهر لك خطأ في object يفيد بأنّك بحاجة إلى تجاهل الطرق. ضَع المؤشر على object، واضغط على Option+Enter (Mac) أو Alt+Enter (Windows) لفتح قائمة "النوايا"، ثم تجاهِل الطريقة getSpanSize().
  1. في نص الدالة getSpanSize()، أعِد حجم الامتداد المناسب لكل موضع. الموضع 0 لديه حجم مدى يبلغ 3، بينما المواضع الأخرى لديها حجم مدى يبلغ 1. يجب أن يبدو الرمز المكتمل على النحو التالي:
    manager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
            override fun getSpanSize(position: Int) =  when (position) {
                0 -> 3
                else -> 1
            }
        }
  1. لتحسين مظهر العنوان، افتح header.xml وأضِف الرمز التالي إلى ملف التصميم header.xml.
android:textColor="@color/white_text_color"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:background="@color/colorAccent"
  1. شغِّل تطبيقك. من المفترض أن يظهر بالشكل الموضّح في لقطة الشاشة أدناه.

تهانينا! لقد أنهيت الخطوات.

مشروع "استوديو Android": RecyclerViewHeaders

  • العنوان هو بشكل عام عنصر يمتد على عرض القائمة ويعمل كعنوان أو فاصل. يمكن أن تحتوي القائمة على عنوان واحد لوصف محتوى العنصر، أو عناوين متعددة لتجميع العناصر وفصلها عن بعضها البعض.
  • يمكن أن يستخدم RecyclerView عناصر متعددة لعرض المحتوى لاستيعاب مجموعة غير متجانسة من العناصر، مثل العناوين وعناصر القائمة.
  • إحدى طرق إضافة العناوين هي تعديل المحوّل لاستخدام ViewHolder مختلف من خلال التحقّق من الفهارس التي يجب عرض العنوان فيها. يكون Adapter مسؤولاً عن تتبُّع العنوان.
  • هناك طريقة أخرى لإضافة العناوين وهي تعديل مجموعة البيانات الأساسية (القائمة) لجدول البيانات، وهو ما فعلته في هذا الدرس التطبيقي.

في ما يلي الخطوات الرئيسية لإضافة عنوان صفحة:

  • جرِّد البيانات في قائمتك من خلال إنشاء DataItem يمكنه الاحتفاظ بعناوين أو بيانات.
  • أنشِئ عنصر نائب للعرض يتضمّن تصميمًا للعنوان في المحوّل.
  • عدِّل المحوّل وطُرق استخدامه لاستخدام أي نوع من RecyclerView.ViewHolder.
  • في onCreateViewHolder()، أعِد النوع الصحيح من عنصر العرض الخاص بعنصر البيانات.
  • عدِّل SleepNightDiffCallback ليتوافق مع الصف DataItem.
  • أنشئ دالة addHeaderAndSubmitList() تستخدم إجراءات فرعية متزامنة لإضافة العنوان إلى مجموعة البيانات، ثم استدعِ submitList().
  • نفِّذ GridLayoutManager.SpanSizeLookup() لجعل العنوان فقط بعرض ثلاث مساحات.

دورة Udacity التدريبية:

مستندات مطوّري تطبيقات Android:

يسرد هذا القسم مهامًا منزلية محتملة للطلاب الذين يعملون على هذا الدرس التطبيقي العملي كجزء من دورة تدريبية يقودها مدرّب. على المعلّم تنفيذ ما يلي:

  • حدِّد واجبًا منزليًا إذا لزم الأمر.
  • توضيح كيفية إرسال الواجبات المنزلية للطلاب
  • وضع درجات للواجبات المنزلية

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

إذا كنت تعمل على هذا الدرس العملي بنفسك، يمكنك استخدام مهام الواجب المنزلي هذه لاختبار معلوماتك.

الإجابة عن هذه الأسئلة

السؤال 1

أيّ من العبارات التالية صحيحة في ما يتعلّق بـ ViewHolder؟

‫▢ يمكن للمحوّل استخدام فئات ViewHolder متعددة لتضمين العناوين وأنواع مختلفة من البيانات.

▢ يمكنك الحصول على عنصر تحكّم واحد فقط في العرض للبيانات، وعنصر تحكّم واحد في العرض للعنوان.

▢ يمكن أن يتوافق تنسيق RecyclerView مع أنواع متعددة من العناوين، ولكن يجب أن تكون البيانات موحّدة.

▢ عند إضافة عنوان، عليك إنشاء فئة فرعية من RecyclerView لإدراج العنوان في الموضع الصحيح.

السؤال 2

متى يجب استخدام الروتينات المشتركة مع RecyclerView؟ اختَر كل العبارات الصحيحة.

▢ أبدًا RecyclerView هو عنصر واجهة مستخدم ويجب ألا يستخدم إجراءات فرعية.

▢ استخدام إجراءات روتينية للمهام الطويلة التي قد تؤدي إلى إبطاء واجهة المستخدم

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

▢ استخدِم إجراءات روتينية مع دوال تعليق لتجنُّب حظر سلسلة التعليمات الرئيسية.

السؤال 3

أيّ مما يلي ليس عليك فعله عند استخدام أكثر من ViewHolder؟

▢ في ViewHolder، قدِّم ملفات تخطيط متعددة لتوسيعها حسب الحاجة.

▢ في onCreateViewHolder()، أعِد النوع الصحيح من حاوية العرض لعنصر البيانات.

‫▢ في onBindViewHolder()، لا تربط البيانات إلا إذا كان عنصر العرض هو النوع الصحيح من عناصر العرض لعنصر البيانات.

▢ تعميم توقيع فئة المحوّل البرمجي لقبول أي RecyclerView.ViewHolder

ابدأ الدرس التالي: 8.1 الحصول على بيانات من الإنترنت

للحصول على روابط تؤدي إلى دروس تطبيقية أخرى في هذه الدورة التدريبية، اطّلِع على الصفحة المقصودة الخاصة بالدروس التطبيقية حول أساسيات Android Kotlin.