ה-codelab הזה הוא חלק מהקורס Android Kotlin Fundamentals. כדי להפיק את המרב מהקורס הזה, מומלץ לעבוד על ה-codelabs לפי הסדר. כל ה-codelab של הקורס מפורטים בדף הנחיתה של ה-codelab בנושא יסודות Kotlin ל-Android.
מבוא
ב-codelab הזה נסביר איך להוסיף כותרת שמשתרעת לרוחב הרשימה שמוצגת ב-RecyclerView
. המשך של בניית אפליקציית מעקב השינה מ-codelabs קודמים.
מה שכדאי לדעת
- איך לבנות ממשק משתמש בסיסי באמצעות פעילות, רכיבים ותצוגות.
- איך לנווט בין פרגמנטים ואיך להשתמש ב-
safeArgs
כדי להעביר נתונים בין פרגמנטים. - אפשר לראות את המודלים, את מפעלי המודלים, את הטרנספורמציות ואת
LiveData
ואת האובזרברים שלהם. - איך יוצרים מסד נתונים של
Room
, יוצרים DAO ומגדירים ישויות. - איך משתמשים ב-coroutines לאינטראקציות עם מסדי נתונים ולמשימות אחרות שפועלות לאורך זמן.
- איך מטמיעים
RecyclerView
בסיסי עםAdapter
,ViewHolder
ופריסת פריטים. - איך מטמיעים קשירת נתונים ב-
RecyclerView
. - איך יוצרים מתאמי קישור ומשתמשים בהם כדי לבצע טרנספורמציה של נתונים.
- איך משתמשים ב-
GridLayoutManager
. - איך לתעד ולטפל בקליקים על פריטים ב
RecyclerView.
מה תלמדו
- איך משתמשים ביותר מ-
ViewHolder
עםRecyclerView
כדי להוסיף פריטים בפריסה שונה. בפרט, איך משתמשים ב-ViewHolder
שני כדי להוסיף כותרת מעל הפריטים שמוצגים ב-RecyclerView
.
הפעולות שתבצעו:
- המשך פיתוח של אפליקציית TrackMySleepQuality מתוך ה-codelab הקודם בסדרה הזו.
- מוסיפים כותרת שמשתרעת לרוחב המסך מעל הלילות שמוצגים ב-
RecyclerView
.
אפליקציית מעקב השינה שמתחילים איתה כוללת שלושה מסכים, שמיוצגים על ידי רכיבי Fragment, כמו שמוצג באיור שלמטה.
במסך הראשון, שמוצג בצד ימין, יש לחצנים להפעלה ולהפסקה של המעקב. במסך מוצגים חלק מנתוני השינה של המשתמש. הלחצן ניקוי מוחק באופן סופי את כל הנתונים שהאפליקציה אספה על המשתמש. במסך השני, שמוצג באמצע, בוחרים את דירוג איכות השינה. המסך השלישי הוא תצוגת פרטים שנפתחת כשהמשתמש מקיש על פריט ברשת.
האפליקציה הזו משתמשת בארכיטקטורה פשוטה עם בקר ממשק משתמש, מודל תצוגה ו-LiveData
, ומסד נתונים Room
כדי לשמור את נתוני השינה.
ב-codelab הזה מוסיפים כותרת לרשת הפריטים שמוצגת. המסך הראשי הסופי ייראה כך:
ב-codelab הזה נלמד את העיקרון הכללי של הכללת פריטים שמשתמשים בפריסות שונות ב-RecyclerView
. דוגמה נפוצה היא שימוש בכותרות ברשימה או ברשת. לרשימה יכולה להיות כותרת אחת שמתארת את תוכן הפריט. רשימה יכולה לכלול גם כמה כותרות כדי לקבץ ולהפריד בין פריטים ברשימה אחת.
RecyclerView
לא יודע דבר על הנתונים שלכם או על סוג הפריסה של כל פריט. LayoutManager
מסדר את הפריטים במסך, אבל המתאם מעבד את הנתונים כדי להציג אותם ומעביר את מחזיקי התצוגה אל LayoutManager
.RecyclerView
לכן, תוסיפו את הקוד ליצירת כותרות במתאם.
שתי דרכים להוספת כותרות
ב-RecyclerView
, כל פריט ברשימה תואם למספר אינדקס שמתחיל מ-0. לדוגמה:
[Actual Data] -> [Adapter Views]
[0: SleepNight] -> [0: SleepNight]
[1: SleepNight] -> [1: SleepNight]
[2: SleepNight] -> [2: SleepNight]
דרך אחת להוסיף כותרות לרשימה היא לשנות את המתאם כך שישתמש ב-ViewHolder
אחר על ידי סימון אינדקסים שבהם צריך להציג את הכותרת. ה-Adapter
יהיה אחראי למעקב אחרי הכותרת. לדוגמה, כדי להציג כותרת בראש הטבלה, צריך להחזיר ViewHolder
שונה לכותרת בזמן הפריסה של הפריט עם האינדקס אפס. לאחר מכן, כל הפריטים האחרים ימופו עם ההיסט של הכותרת, כמו שמוצג בהמשך.
[Actual Data] -> [Adapter Views]
[0: Header]
[0: SleepNight] -> [1: SleepNight]
[1: SleepNight] -> [2: SleepNight]
[2: SleepNight] -> [3: SleepNight.
דרך נוספת להוסיף כותרות היא לשנות את מערך הנתונים הבסיסי של טבלת הנתונים. מכיוון שכל הנתונים שצריך להציג מאוחסנים ברשימה, אפשר לשנות את הרשימה כך שתכלול פריטים שייצגו כותרת. השיטה הזו קצת יותר פשוטה להבנה, אבל היא מחייבת לחשוב על עיצוב האובייקטים כדי שאפשר יהיה לשלב את סוגי הפריטים השונים ברשימה אחת. אם מטמיעים את המתאם בצורה הזו, הוא יציג את הפריטים שמועברים אליו. לכן, הפריט במיקום 0 הוא כותרת, והפריט במיקום 1 הוא SleepNight
, שמוצג ישירות על המסך.
[Actual Data] -> [Adapter Views]
[0: Header] -> [0: Header]
[1: SleepNight] -> [1: SleepNight]
[2: SleepNight] -> [2: SleepNight]
[3: SleepNight] -> [3: SleepNight]
לכל מתודולוגיה יש יתרונות וחסרונות. שינוי מערך הנתונים לא משפיע על שאר קוד המתאם, ואפשר להוסיף לוגיקה של כותרות על ידי שינוי רשימת הנתונים. מצד שני, שימוש ב-ViewHolder
אחר על ידי בדיקת אינדקסים של כותרות מאפשר יותר חופש בפריסת הכותרת. המתאם גם מאפשר לטפל באופן שבו הנתונים מותאמים לתצוגה בלי לשנות את נתוני הבסיס.
ב-codelab הזה, מעדכנים את RecyclerView
כדי להציג כותרת בתחילת הרשימה. במקרה כזה, האפליקציה תשתמש ב-ViewHolder
שונה לכותרת ולפריטי הנתונים. האפליקציה תבדוק את האינדקס של הרשימה כדי לקבוע באיזה ViewHolder
להשתמש.
שלב 1: יוצרים מחלקה DataItem
כדי להפשיט את סוג הפריט ולאפשר למתאם להתמודד רק עם 'פריטים', אפשר ליצור מחזיק נתונים שמייצג SleepNight
או Header
. מערך הנתונים יהיה רשימה של פריטים של בעלי נתונים.
אפשר להוריד את אפליקציית המתחילים מ-GitHub, או להמשיך להשתמש באפליקציית SleepTracker שיצרתם בסדנת הקוד הקודמת.
- מורידים את הקוד RecyclerViewHeaders-Starter מ-GitHub. הספרייה RecyclerViewHeaders-Starter מכילה את גרסת ההתחלה של אפליקציית SleepTracker שנדרשת ל-codelab הזה. אם רוצים, אפשר גם להמשיך לעבוד על האפליקציה שסיימתם ליצור בסדנת הקוד הקודמת.
- פותחים את הקובץ SleepNightAdapter.kt.
- מתחת לכיתה
SleepNightListener
, ברמה העליונה, מגדירים כיתהsealed
בשםDataItem
שמייצגת פריט נתונים.
מחלקתsealed
מגדירה סוג סגור, כלומר כל מחלקות המשנה שלDataItem
חייבות להיות מוגדרות בקובץ הזה. כתוצאה מכך, מספר מחלקות המשנה ידוע לקומפיילר. חלק אחר בקוד לא יכול להגדיר סוג חדש שלDataItem
שעלול לשבור את המתאם.
sealed class DataItem {
}
- בתוך הגוף של המחלקה
DataItem
, מגדירים שתי מחלקות שמייצגות את הסוגים השונים של פריטי הנתונים. הראשון הואSleepNightItem
, שהוא wrapper סביבSleepNight
, ולכן הוא מקבל ערך יחיד שנקראsleepNight
. כדי להפוך אותו לחלק מהכיתה החתומה, צריך להרחיב אותוDataItem
.
data class SleepNightItem(val sleepNight: SleepNight): DataItem()
- המחלק השני הוא
Header
, שמייצג כותרת. מכיוון שלכותרת אין נתונים בפועל, אפשר להגדיר אותה כ-object
. כלומר, תמיד יהיה רק מופע אחד שלHeader
. שוב, מאריכים את התקופהDataItem
.
object Header: DataItem()
- בתוך
DataItem
, ברמת המחלקה, מגדירים מאפייןabstract
Long
בשםid
. כשהמתאם משתמש ב-DiffUtil
כדי לקבוע אם פריט השתנה ואיך הוא השתנה, ה-DiffItemCallback
צריך לדעת את המזהה של כל פריט. תופיע שגיאה, כי הפונקציותSleepNightItem
ו-Header
צריכות לבטל את המאפיין המופשטid
.
abstract val id: Long
- ב
SleepNightItem
, שינוי מברירת המחדל שלid
כדי להחזיר אתnightId
.
override val id = sleepNight.nightId
- ב-
Header
, מחליפים אתid
כדי להחזיר את הערךLong.MIN_VALUE
, שהוא מספר קטן מאוד (במילים אחרות, -2 בחזקת 63). לכן, הוא אף פעם לא יתנגש עם אףnightId
קיים.
override val id = Long.MIN_VALUE
- הקוד הסופי אמור להיראות כך, והאפליקציה אמורה להיבנות ללא שגיאות.
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 לכותרת
- יוצרים את הפריסה של הכותרת בקובץ חדש של משאבי פריסה בשם 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" />
- מחלקים את
"Sleep Results"
למשאב מחרוזת וקוראים לוheader_text
.
<string name="header_text">Sleep Results</string>
- ב-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
, הוא צריך להיות מסוגל להשתמש בכל סוג של מחזיק תצוגה.
הגדרת סוגי הפריטים
- ב-
SleepNightAdapter.kt
, ברמה העליונה, מתחת להצהרותimport
ומעלSleepNightAdapter
, מגדירים שתי קבועים לסוגי התצוגה.
ה-RecyclerView
יצטרך להבחין בין סוגי התצוגה של כל פריט, כדי שיוכל להקצות לו מחזיק תצוגה בצורה נכונה.
private val ITEM_VIEW_TYPE_HEADER = 0
private val ITEM_VIEW_TYPE_ITEM = 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
- בהגדרה של
SleepNightAdapter
, מעדכנים את הארגומנט הראשון שלListAdapter
מ-SleepNight
ל-DataItem
. - בהגדרה של
SleepNightAdapter
, משנים את הארגומנט הגנרי השני שלListAdapter
מ-SleepNightAdapter.ViewHolder
ל-RecyclerView.ViewHolder
. יוצגו כמה שגיאות לגבי עדכונים נדרשים, וכותרת הכיתה אמורה להיראות כמו בדוגמה שלמטה.
class SleepNightAdapter(val clickListener: SleepNightListener):
ListAdapter<DataItem, RecyclerView.ViewHolder>(SleepNightDiffCallback()) {
עדכון של onCreateViewHolder()
- משנים את החתימה של
onCreateViewHolder()
כדי להחזירRecyclerView.ViewHolder
.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder
- מרחיבים את ההטמעה של השיטה
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()
- שינוי סוג הפרמטר של
onBindViewHolder()
מ-ViewHolder
ל-RecyclerView.ViewHolder
.
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int)
- מוסיפים תנאי כדי להקצות נתונים לבעל התצוגה רק אם הבעלים הוא
ViewHolder
.
when (holder) {
is ViewHolder -> {...}
- מבצעים המרה (cast) של סוג האובייקט שמוחזר על ידי
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)
}
}
}
עדכון של קריאות חוזרות (callbacks) של diffUtil
- משנים את השיטות ב-
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
}
}
הוספה ושליחה של הכותרת
- בתוך
SleepNightAdapter
, מתחת ל-onCreateViewHolder()
, מגדירים פונקציהaddHeaderAndSubmitList()
כמו שמוצג בהמשך. הפונקציה הזו מקבלת רשימה שלSleepNight
. במקום להשתמש ב-submitList()
, שמופיע ב-ListAdapter
, כדי לשלוח את הרשימה, תשתמשו בפונקציה הזו כדי להוסיף כותרת ואז לשלוח את הרשימה.
fun addHeaderAndSubmitList(list: List<SleepNight>?) {}
- בתוך
addHeaderAndSubmitList()
, אם הרשימה שהועברה היאnull
, מחזירים רק כותרת. אחרת, מצרפים את הכותרת לראש הרשימה ושולחים את הרשימה.
val items = when (list) {
null -> listOf(DataItem.Header)
else -> listOf(DataItem.Header) + list.map { DataItem.SleepNightItem(it) }
}
submitList(items)
- פותחים את SleepTrackerFragment.kt ומשנים את הקריאה ל-
submitList()
ל-addHeaderAndSubmitList()
.
- מריצים את האפליקציה ומתבוננים באופן שבו הכותרת מוצגת כפריט הראשון ברשימת פריטי השינה.
יש שתי בעיות שצריך לתקן באפליקציה הזו. אחת מהן גלויה והשנייה לא.
- הכותרת מופיעה בפינה הימנית העליונה, ולא קל להבחין בה.
- זה לא משנה הרבה ברשימה קצרה עם כותרת אחת, אבל לא מומלץ לבצע מניפולציות ברשימה ב-
addHeaderAndSubmitList()
בשרשור של ממשק המשתמש. תארו לעצמכם רשימה עם מאות פריטים, כמה כותרות והיגיון שקובע איפה צריך להוסיף את הפריטים. העבודה הזו שייכת לקורוטינה.
שינוי addHeaderAndSubmitList()
לשימוש בקורוטינות:
- ברמה העליונה בתוך הכיתה
SleepNightAdapter
, מגדיריםCoroutineScope
באמצעותDispatchers.Default
.
private val adapterScope = CoroutineScope(Dispatchers.Default)
- ב-
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)
}
}
}
- הקוד אמור להיבנות ולפעול, ולא תראו הבדל.
בשלב הזה, רוחב הכותרת זהה לרוחב של שאר הפריטים ברשת, והיא תופסת טווח אחד אופקית ואנכית. כל הרשת מתאימה לשלושה פריטים ברוחב של span אחד לרוחב, ולכן הכותרת צריכה להשתמש בשלושה spans לרוחב.
כדי לתקן את רוחב הכותרת, צריך לציין ל-GridLayoutManager
מתי להרחיב את הנתונים על פני כל העמודות. כדי לעשות את זה, צריך להגדיר את SpanSizeLookup
ב-GridLayoutManager
. זהו אובייקט הגדרה שרכיב GridLayoutManager
משתמש בו כדי לקבוע כמה תגי span יש להשתמש בהם לכל פריט ברשימה.
- פותחים את SleepTrackerFragment.kt.
- מחפשים את הקוד שבו מוגדר
manager
, לקראת סוףonCreateView()
.
val manager = GridLayoutManager(activity, 3)
- מתחת ל-
manager
, מגדירים אתmanager.spanSizeLookup
, כמו שמוצג. צריך ליצורobject
כיsetSpanSizeLookup
לא מקבל lambda. כדי ליצורobject
ב-Kotlin, מקלידיםobject : classname
, במקרה הזהGridLayoutManager.SpanSizeLookup
.
manager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
}
- יכול להיות שתקבלו שגיאת קומפילציה כדי לקרוא לבונה. אם כן, פותחים את תפריט הכוונות באמצעות
Option+Enter
(Mac) אוAlt+Enter
(Windows) כדי להחיל את קריאת הבונה.
- לאחר מכן תופיע שגיאה ב-
object
עם הודעה שצריך לבטל את השיטות. מציבים את הסמן עלobject
, מקישים עלOption+Enter
(ב-Mac) או עלAlt+Enter
(ב-Windows) כדי לפתוח את תפריט הכוונות, ואז משנים את השיטהgetSpanSize()
.
- בגוף של
getSpanSize()
, מחזירים את גודל הטווח הנכון לכל מיקום. המיקום 0 הוא בגודל 3, ושאר המיקומים הם בגודל 1. הקוד המלא צריך להיראות כמו הקוד שבהמשך:
manager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int) = when (position) {
0 -> 3
else -> 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"
- מריצים את האפליקציה. היא אמורה להיראות כמו בצילום המסך שלמטה.
מעולה! סיימת.
פרויקט Android Studio: RecyclerViewHeaders
- כותרת היא בדרך כלל פריט שמשתרע לרוחב הרשימה ומשמש ככותרת או כמפריד. רשימה יכולה לכלול כותרת אחת שמתארת את תוכן הפריט, או כמה כותרות שמקבצות פריטים ומפרידות ביניהם.
RecyclerView
יכול להשתמש בכמה מחזיקי תצוגה כדי להכיל קבוצה הטרוגנית של פריטים, למשל כותרות ופריטים ברשימה.- דרך אחת להוסיף כותרות היא לשנות את המתאם כך שישתמש ב-
ViewHolder
אחר על ידי בדיקת האינדקסים שבהם צריך להציג את הכותרת. ה-Adapter
אחראי למעקב אחרי הכותרת. - דרך נוספת להוסיף כותרות היא לשנות את מערך הנתונים הבסיסי (הרשימה) של רשת הנתונים, כמו שעשיתם ב-codelab הזה.
אלה השלבים העיקריים להוספת כותרת:
- כדי להפוך את הנתונים ברשימה למופשטים, יוצרים
DataItem
שיכול להכיל כותרת או נתונים. - יוצרים מחזיק תצוגה עם פריסה לכותרת במתאם.
- מעדכנים את המתאם ואת השיטות שלו כדי להשתמש בכל סוג של
RecyclerView.ViewHolder
. - ב-
onCreateViewHolder()
, מחזירים את הסוג הנכון של מחזיק התצוגה עבור פריט הנתונים. - צריך לעדכן את
SleepNightDiffCallback
כדי לעבוד עם הכיתהDataItem
. - יוצרים פונקציית
addHeaderAndSubmitList()
שמשתמשת ב-coroutines כדי להוסיף את הכותרת למערך הנתונים, ואז קוראת ל-submitList()
. - מטמיעים את
GridLayoutManager.SpanSizeLookup()
כדי שהכותרת תהיה ברוחב של שלוש תגי span בלבד.
קורס ב-Udacity:
מסמכי תיעוד למפתחי Android:
בקטע הזה מפורטות אפשרויות למשימות ביתיות לתלמידים שעובדים על ה-Codelab הזה כחלק מקורס בהנחיית מדריך. המורה צריך:
- אם צריך, מקצים שיעורי בית.
- להסביר לתלמידים איך להגיש מטלות.
- בודקים את שיעורי הבית.
אנשי ההוראה יכולים להשתמש בהצעות האלה כמה שרוצים, ומומלץ להם להקצות כל שיעורי בית אחרים שהם חושבים שמתאימים.
אם אתם עובדים על ה-codelab הזה לבד, אתם יכולים להשתמש במשימות האלה כדי לבדוק את הידע שלכם.
עונים על השאלות הבאות
שאלה 1
איזו מההצהרות הבאות נכונה לגבי ViewHolder
?
▢ מתאם יכול להשתמש בכמה מחלקות ViewHolder
כדי להכיל כותרות וסוגים שונים של נתונים.
▢ יכול להיות לכם בדיוק מחזיק תצוגה אחד לנתונים ומחזיק תצוגה אחד לכותרת.
▢ RecyclerView
תומך בכמה סוגים של כותרות, אבל הנתונים צריכים להיות אחידים.
▢ כשמוסיפים כותרת, יוצרים מחלקת משנה של RecyclerView
כדי להוסיף את הכותרת במיקום הנכון.
שאלה 2
מתי כדאי להשתמש בקורוטינות עם RecyclerView
? צריך לבחור את כל ההצהרות הנכונות.
▢ אף פעם. RecyclerView
הוא רכיב בממשק המשתמש, ולכן אסור להשתמש בו ברוטינות משנה.
▢ שימוש בקורוטינות למשימות לטווח ארוך שעלולות להאט את ממשק המשתמש.
▢ פעולות על רשימות יכולות לקחת הרבה זמן, ותמיד צריך לבצע אותן באמצעות קורוטינות.
▢ משתמשים ב-coroutines עם פונקציות השהיה כדי להימנע מחסימה של ה-thread הראשי.
שאלה 3
איזו מהפעולות הבאות לא צריך לבצע כשמשתמשים ביותר מ-ViewHolder
אחד?
▢ ב-ViewHolder
, מספקים כמה קובצי פריסה להרחבה לפי הצורך.
▢ ב-onCreateViewHolder()
, מחזירים את הסוג הנכון של מחזיק התצוגה עבור פריט הנתונים.
▢ ב-onBindViewHolder()
, מתבצעת קשירת נתונים רק אם מחזיק התצוגה הוא הסוג הנכון של מחזיק התצוגה עבור פריט הנתונים.
▢ הכללה של חתימת המחלקה של המתאם כדי לקבל כל RecyclerView.ViewHolder
.
עוברים לשיעור הבא:
קישורים ל-codelabs אחרים בקורס הזה מופיעים בדף הנחיתה של ה-codelabs בנושא יסודות Android Kotlin.