אפליקציות רבות צריכות להציג אוספים של פריטים. במסמך הזה מוסבר איך יכול לעשות זאת ביעילות ב-Jetpack פיתוח נייטיב.
אם ידוע לך שהתרחיש לדוגמה שלך לא דורש גלילה, תוכל
משתמשים Column
או Row
פשוטים (בהתאם לכיוון), ופולטים את התוכן של כל פריט באמצעות
חזרה על רשימה מסוימת באופן הבא:
@Composable fun MessageList(messages: List<Message>) { Column { messages.forEach { message -> MessageRow(message) } } }
נוכל לגרום לגלילה Column
באמצעות הצירוף verticalScroll()
.
רשימות עצלות
אם אתם צריכים להציג מספר גדול של פריטים (או רשימה באורך לא ידוע),
פריסה כמו Column
יכולה לגרום לבעיות בביצועים, כי כל הפריטים יורכבו ויוצגו אם הם גלויים או לא.
הרכיב 'פיתוח נייטיב' מספק קבוצה של רכיבים שמרכיבים ופורסים רק פריטים
גלויות באזור התצוגה של הרכיב. הרכיבים האלה כוללים
LazyColumn
וגם
LazyRow
כפי שהשם מרמז, ההבדל בין
LazyColumn
וגם
LazyRow
הוא הכיוון שבו הם פורסים את הפריטים וגוללים. LazyColumn
יוצרת רשימת גלילה אנכית, ו-LazyRow
יוצרת רשימה אופקית
רשימה של גלילה.
הרכיבים העצמיים שונים מרוב הפריסות בכלי 'פיתוח נייטיב'. במקום
קבלת הפרמטר @Composable
של חסימת תוכן, שמאפשרת לאפליקציות ישירות
פולטים תכנים קומפוזביליים, רכיבי Lazy מספקים בלוק LazyListScope.()
. הזה
LazyListScope
בלוק DSL שמאפשר לאפליקציות לתאר את תוכן הפריט.
לאחר מכן, רכיב המעקב אחראי להוספת התוכן של כל פריט בתור
בהתאם לפריסה ולמיקום הגלילה.
DSL: LazyListScope
ה-DSL של LazyListScope
מספק כמה פונקציות לתיאור פריטים
בפריסה. ברמה הבסיסית ביותר,
item()
מוסיף פריט יחיד,
items(Int)
מוסיף פריטים מרובים:
LazyColumn { // Add a single item item { Text(text = "First item") } // Add 5 items items(5) { index -> Text(text = "Item: $index") } // Add another single item item { Text(text = "Last item") } }
יש גם כמה פונקציות של תוספים שמאפשרות להוסיף
אוספים של פריטים, כמו List
. התוספים האלה מאפשרים לנו
להעביר את הדוגמה Column
מלמעלה:
/** * import androidx.compose.foundation.lazy.items */ LazyColumn { items(messages) { message -> MessageRow(message) } }
יש גם וריאציה של
items()
נקראת פונקציית התוסף
itemsIndexed()
,
שמספק את האינדקס. כדאי לעיין
LazyListScope
לקבלת פרטים נוספים.
רשתות עצלות
LazyVerticalGrid
וגם
LazyHorizontalGrid
תכנים קומפוזביליים מספקים תמיכה בהצגת פריטים ברשת. רשת אנכית מדורגת
תציג את הפריטים בתוך מאגר שניתן לגלול בו לאורך, לרוחב
עמודות רבות, בעוד שהרשתות האופקיות 'לאזיות' יפעלו באופן זהה
על הציר האופקי.
לרשתות יש את אותן יכולות API עוצמתיות כמו לרשימות, והן גם משתמשות
DSL דומה מאוד -
LazyGridScope.()
לתיאור התוכן.
הפרמטר columns
בתוך
LazyVerticalGrid
ו-rows
ב-
LazyHorizontalGrid
לקבוע איך תאים נוצרים בעמודות או שורות. הבאים
מציגה פריטים ברשת, באמצעות
GridCells.Adaptive
כדי להגדיר כל עמודה ברוחב של 128.dp
לפחות:
LazyVerticalGrid( columns = GridCells.Adaptive(minSize = 128.dp) ) { items(photos) { photo -> PhotoItem(photo) } }
LazyVerticalGrid
מאפשרת לציין רוחב של פריטים, ואז הרשת
להתאים כמה שיותר עמודות. כל הרוחב שנותר מחולק באופן שווה
בין העמודות, לאחר חישוב מספר העמודות.
הדרך הזו לשינוי גודל שימושית במיוחד להצגת קבוצות של פריטים
במסכים בגדלים שונים.
אם אתם יודעים את המספר המדויק של העמודות שבהן צריך להשתמש, אפשר במקום זאת לציין
מופע של
GridCells.Fixed
שמכיל את מספר העמודות הנדרשות.
אם העיצוב דורש שרק פריטים מסוימים יהיו במידות לא סטנדרטיות,
אפשר להשתמש בתמיכה ברשת כדי לספק עמודות מותאמות אישית לפריטים.
צריך לציין את טווח העמודה עם הפרמטר span
של
LazyGridScope DSL
item
ו-items
.
maxLineSpan
אחד מהערכים של היקף ה-span, הוא שימושי במיוחד כשמשתמשים
שינוי גודל מותאם, כי מספר העמודות לא קבוע
בדוגמה הזו מוסבר איך לציין טווח שורה מלא:
LazyVerticalGrid( columns = GridCells.Adaptive(minSize = 30.dp) ) { item(span = { // LazyGridItemSpanScope: // maxLineSpan GridItemSpan(maxLineSpan) }) { CategoryCard("Fruits") } // ... }
רשת מדורגת
LazyVerticalStaggeredGrid
וגם
LazyHorizontalStaggeredGrid
הם תכנים קומפוזביליים שמאפשרים ליצור רשת של פריטים בטעינה מדורגת.
רשת מדורגת אנכית שמציגה את הפריטים שבה מוצגים בטבלה שניתן לגלול אנכית
מאגר שמתפרס על כמה עמודות ומאפשר הצגה של פריטים בודדים
לגבהים שונים. לרשתות אופקיות עצלות יש התנהגות זהה
ציר אופקי עם פריטים ברוחב שונה.
קטע הקוד הבא הוא דוגמה בסיסית לשימוש ב-LazyVerticalStaggeredGrid
עם רוחב של 200.dp
לכל פריט:
LazyVerticalStaggeredGrid( columns = StaggeredGridCells.Adaptive(200.dp), verticalItemSpacing = 4.dp, horizontalArrangement = Arrangement.spacedBy(4.dp), content = { items(randomSizedPhotos) { photo -> AsyncImage( model = photo, contentScale = ContentScale.Crop, contentDescription = null, modifier = Modifier.fillMaxWidth().wrapContentHeight() ) } }, modifier = Modifier.fillMaxSize() )
כדי להגדיר מספר קבוע של עמודות, אפשר להשתמש בפונקציה
StaggeredGridCells.Fixed(columns)
במקום StaggeredGridCells.Adaptive
.
פעולה זו מחלקת את הרוחב הזמין במספר העמודות (או שורות עבור
רשת אופקית), וכל פריט תופס את הרוחב (או הגובה) הזה
רשת אופקית):
LazyVerticalStaggeredGrid( columns = StaggeredGridCells.Fixed(3), verticalItemSpacing = 4.dp, horizontalArrangement = Arrangement.spacedBy(4.dp), content = { items(randomSizedPhotos) { photo -> AsyncImage( model = photo, contentScale = ContentScale.Crop, contentDescription = null, modifier = Modifier.fillMaxWidth().wrapContentHeight() ) } }, modifier = Modifier.fillMaxSize() )
![רשת זזה של תמונות מדורגת ב'פיתוח'](https://developer.android.com/static/develop/ui/compose/images/lists/staggered_grid_fixed.png?authuser=8&hl=he)
המרווח הפנימי של התוכן
לפעמים צריך להוסיף מרווח פנימי סביב שולי התוכן. העצלנים
מאפשרים להעביר
PaddingValues
לפרמטר contentPadding
כדי לתמוך בכך:
LazyColumn( contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp), ) { // ... }
בדוגמה זו, אנחנו מוסיפים מרווח פנימי 16.dp
לקצוות האופקיים (בצד שמאל
משמאל), ולאחר מכן 8.dp
לחלק העליון והתחתון של התוכן.
לתשומת ליבך, המרווח הפנימי חל על התוכן, ולא על
LazyColumn
עצמו. בדוגמה שלמעלה, הפריט הראשון יוסיף את 8.dp
מרווח פנימי לחלק העליון, הפריט האחרון יוסיף 8.dp
לחלק התחתון שלו וכל הפריטים
יכלול מרווח פנימי 16.dp
בצד שמאל ובצד ימין.
ריווח בין תוכן
כדי להוסיף ריווח בין פריטים, ניתן להשתמש ב
Arrangement.spacedBy()
הדוגמה הבאה מוסיפה שטח אחסון של 4.dp
בין כל פריט:
LazyColumn( verticalArrangement = Arrangement.spacedBy(4.dp), ) { // ... }
באופן דומה עבור LazyRow
:
LazyRow( horizontalArrangement = Arrangement.spacedBy(4.dp), ) { // ... }
עם זאת, רשתות יכולות לקבל גם סידורים אנכיים וגם סידורים אופקיים:
LazyVerticalGrid( columns = GridCells.Fixed(2), verticalArrangement = Arrangement.spacedBy(16.dp), horizontalArrangement = Arrangement.spacedBy(16.dp) ) { items(photos) { item -> PhotoItem(item) } }
מפתחות של פריטים
כברירת מחדל, המצב של כל פריט מוצמד למיקום של הפריט
תצוגת רשימה או רשת. עם זאת, הדבר עלול לגרום לבעיות אם מערך הנתונים משתנה, מכיוון שפריטים
כשמשנים את המיקום למעשה מאבדים כל מצב ששמור בזיכרון. אם נגיד
תרחיש של LazyRow
בתוך LazyColumn
, אם השורה משנה את מיקום הפריט,
לאחר מכן המשתמש יאבד את מיקום הגלילה שלו בתוך השורה.
כדי להילחם בכך, אפשר לספק מפתח יציב וייחודי לכל פריט, ולספק
בלוק לפרמטר key
. מתן מפתח יציב מאפשר למצב הפריט
עקביים בכל השינויים במערך הנתונים:
LazyColumn { items( items = messages, key = { message -> // Return a stable + unique key for the item message.id } ) { message -> MessageRow(message) } }
הוספת מפתחות עוזרת ל'כתיבה' לטפל בסידור מחדש בצורה נכונה. לדוגמה, אם הפריט מכיל מצב שנשמר בזיכרון, מפתחות ההגדרה יאפשרו הרכב כדי להעביר את המצב הזה יחד עם הפריט, כאשר המיקום שלו משתנה.
LazyColumn { items(books, key = { it.id }) { val rememberedValue = remember { Random.nextInt() } } }
עם זאת, יש מגבלה אחת על הסוגים שבהם אפשר להשתמש כמפתחות של פריטים.
צריכה להיות תמיכה בסוג המפתח על ידי
Bundle
, המנגנון של Android לשמירה
מציין מתי הפעילות נוצרת מחדש. Bundle
תומך בסוגים כמו פרימיטיביים,
טיפוסים בני מנייה (enum) או למגרשים.
LazyColumn { items(books, key = { // primitives, enums, Parcelable, etc. }) { // ... } }
המפתח חייב להיות נתמך על ידי Bundle
כדי שה-rememberSaveable
שבפנים
אפשר לשחזר את התוכן הקומפוזבילי אחרי שחזור הפעילות, או אפילו
כשגוללים אל מחוץ לפריט הזה וגוללים אחורה.
LazyColumn { items(books, key = { it.id }) { val rememberedValue = rememberSaveable { Random.nextInt() } } }
אנימציות של פריטים
אם השתמשתם בווידג'ט של RecyclerView, סימן שהוא מכיל אנימציה של הפריט
משתנה באופן אוטומטי.
פריסות עצלות מספקות את אותה פונקציונליות לסידור מחדש של פריטים.
ה-API פשוט – צריך רק להגדיר
animateItemPlacement
מגביל לתוכן הפריט:
LazyColumn { items(books, key = { it.id }) { Row(Modifier.animateItemPlacement()) { // ... } } }
אפשר גם לספק מפרט אנימציה מותאם אישית, אם אתם צריכים:
LazyColumn { items(books, key = { it.id }) { Row( Modifier.animateItemPlacement( tween(durationMillis = 250) ) ) { // ... } } }
חשוב לספק מפתחות לפריטים כדי שיהיה אפשר למצוא את הפריט החדש המיקום של הרכיב שהועבר.
מלבד שינוי הסדר, אנימציות של פריטים משמשות כרגע להוספות ולהסרות בפיתוח. אפשר לעקוב אחרי ההתקדמות בקטע בעיה 150812265.
כותרות במיקום קבוע (ניסיוני)
הדפוס 'כותרת במיקום קבוע' מועיל בהצגת רשימות של נתונים מקובצים. למטה אפשר לראות דוגמה ל'רשימת אנשי קשר' המקובצת לפי ראשוני:
כדי ליצור כותרת במיקום קבוע באמצעות LazyColumn
, אפשר להשתמש בכלי הניסיוני
stickyHeader()
שמספקת את תוכן הכותרת:
@OptIn(ExperimentalFoundationApi::class) @Composable fun ListWithHeader(items: List<Item>) { LazyColumn { stickyHeader { Header() } items(items) { item -> ItemRow(item) } } }
כדי ליצור רשימה עם כמה כותרות, כמו בדוגמה של 'רשימת אנשי הקשר' שלמעלה, תוכלו לעשות:
// This ideally would be done in the ViewModel val grouped = contacts.groupBy { it.firstName[0] } @OptIn(ExperimentalFoundationApi::class) @Composable fun ContactsList(grouped: Map<Char, List<Contact>>) { LazyColumn { grouped.forEach { (initial, contactsForInitial) -> stickyHeader { CharacterHeader(initial) } items(contactsForInitial) { contact -> ContactListItem(contact) } } } }
תגובה למיקום גלילה
אפליקציות רבות צריכות להגיב ולהאזין למיקום הגלילה ולשינויים בפריסת הפריטים.
הרכיבים של Lazy תומכים בתרחיש לדוגמה הזה על ידי העלאת
LazyListState
:
@Composable fun MessageList(messages: List<Message>) { // Remember our own LazyListState val listState = rememberLazyListState() // Provide it to LazyColumn LazyColumn(state = listState) { // ... } }
בתרחישי שימוש פשוטים, לאפליקציות בדרך כלל צריך לדעת רק מידע על
של הפריט הראשון שמוצג. בשביל זה
LazyListState
מספקת
firstVisibleItemIndex
וגם
firstVisibleItemScrollOffset
נכסים.
אם נשתמש בדוגמה של הצגה והסתרה של לחצן על סמך מצב שבו המשתמש גלל ועובר את הפריט הראשון:
@OptIn(ExperimentalAnimationApi::class) @Composable fun MessageList(messages: List<Message>) { Box { val listState = rememberLazyListState() LazyColumn(state = listState) { // ... } // Show the button if the first visible item is past // the first item. We use a remembered derived state to // minimize unnecessary compositions val showButton by remember { derivedStateOf { listState.firstVisibleItemIndex > 0 } } AnimatedVisibility(visible = showButton) { ScrollToTopButton() } } }
קריאת המצב ישירות במצב היצירה שימושית כשצריך לבצע עדכון
תכנים קומפוזביליים אחרים בממשק המשתמש, אבל יש גם תרחישים שבהם האירוע לא צריך
שצריך לטפל בהם באותה הרכבה. דוגמה נפוצה לכך היא שליחת
אירוע ב-Analytics אחרי שהמשתמש גלל ומעבר לנקודה מסוימת. כדי לטפל בזה
בצורה יעילה, אנחנו יכולים להשתמש
snapshotFlow()
:
val listState = rememberLazyListState() LazyColumn(state = listState) { // ... } LaunchedEffect(listState) { snapshotFlow { listState.firstVisibleItemIndex } .map { index -> index > 0 } .distinctUntilChanged() .filter { it } .collect { MyAnalyticsService.sendScrolledPastFirstItemEvent() } }
LazyListState
מספק גם מידע על כל הפריטים שנמצאים כרגע
על המסך, ועל הגבולות שלהם,
layoutInfo
לנכס. לצפייה
LazyListLayoutInfo
למידע נוסף.
שליטה במיקום הגלילה
בנוסף לתגובה למיקום הגלילה, כדאי גם שאפליקציות יכולות
לשלוט גם במיקום הגלילה.
LazyListState
תומך בכך דרך scrollToItem()
היא שמקליטה באופן מיידי
מעבר למיקום הגלילה, וגם animateScrollToItem()
שגוללת באמצעות אנימציה (שנקראת גם גלילה חלקה):
@Composable fun MessageList(messages: List<Message>) { val listState = rememberLazyListState() // Remember a CoroutineScope to be able to launch val coroutineScope = rememberCoroutineScope() LazyColumn(state = listState) { // ... } ScrollToTopButton( onClick = { coroutineScope.launch { // Animate scroll to the first item listState.animateScrollToItem(index = 0) } } ) }
מערכי נתונים גדולים (חלוקה לדפים)
ספריית הדפים מאפשרת לאפליקציות
לתמוך ברשימות גדולות של פריטים, לטעון ולהציג מקטעי נתונים קטנים של הרשימה
הנחוצים. Paging 3.0 ואילך מספק תמיכה ב-Compose באמצעות
הספרייה androidx.paging:paging-compose
.
כדי להציג רשימה של התוכן בדפים, אפשר להשתמש
collectAsLazyPagingItems()
של פונקציית הרחבה, ואז מעבירים את הפונקציה
LazyPagingItems
אל items()
ב-LazyColumn
. בדומה לתמיכה בהחלפה של תצוגות מפורטות, אפשר
כדי להציג placeholders בזמן טעינת הנתונים, צריך לבדוק אם הערך של item
הוא null
:
@Composable fun MessageList(pager: Pager<Int, Message>) { val lazyPagingItems = pager.flow.collectAsLazyPagingItems() LazyColumn { items( lazyPagingItems.itemCount, key = lazyPagingItems.itemKey { it.id } ) { index -> val message = lazyPagingItems[index] if (message != null) { MessageRow(message) } else { MessagePlaceholder() } } } }
טיפים לשימוש בפריסות מתקדמות
יש כמה טיפים שכדאי לך לקחת בחשבון כדי להבטיח שפריסות לא מבוססות פועלות כמצופה.
יש להימנע משימוש בפריטים בגודל 0 פיקסלים
זה יכול לקרות במקרים שבהם, למשל, אתם מצפים לבצע פעולות אסינכרוניות לאחזר נתונים מסוימים כמו תמונות, כדי למלא את פריטי הרשימה בשלב מאוחר יותר. זה יגרום לפריסה העצלנית להרכיב את כל הפריטים שלה כי הגובה שלהם הוא 0 פיקסלים והוא יכול להתאים את כולם אזור התצוגה. לאחר שהפריטים נטענים והגובה שלהם מורחב, פריסות לא מבוססות יגרום למחיקה של כל הפריטים האחרים שחוברו שלא לצורך. בפעם הראשונה מכיוון שהן לא יכולות להתאים לאזור התצוגה. כדי להימנע מכך, עליך להגדיר גודל ברירת מחדל לפריטים שלך, כדי שהפריסה המושהית תוכל לבצע חישוב נכון של מספר הפריטים שיכולים באמת להתאים לאזור התצוגה:
@Composable fun Item(imageUrl: String) { AsyncImage( model = rememberAsyncImagePainter(model = imageUrl), modifier = Modifier.size(30.dp), contentDescription = null // ... ) }
אם אתם יודעים מה הגודל המשוער של הפריטים אחרי שהנתונים נטענות באופן אסינכרוני, מומלץ לוודא שהמידות של הפריטים יישארו זהים לפני הטעינה ואחריה, לדוגמה, על ידי הוספת כמה placeholders. כך תוכלו לשמור על מיקום הגלילה הנכון.
אין להציב רכיבים שיש בהם גלילה באותו כיוון
הדבר רלוונטי רק למקרים שבהם מקוננים ילדים שניתן לגלול ללא הגדרה מראש
גודל בתוך תבנית הורה אחרת עם גלילה באותו כיוון. לדוגמה, בניסיון
להציב ילד LazyColumn
בלי גובה קבוע בתוך תיבת גלילה אנכית
הורה של Column
:
// throws IllegalStateException Column( modifier = Modifier.verticalScroll(state) ) { LazyColumn { // ... } }
במקום זאת, אפשר לקבל את אותה תוצאה על ידי האריזה של כל התכנים הקומפוזביליים
בתוך הורה אחד של LazyColumn
, ומשתמשים ב-DSL שלו כדי להעביר סוגים שונים של
תוכן. כך אפשר לפטור פריטים בודדים, וכן מספר פריטים ברשימה,
הכול במקום אחד:
LazyColumn { item { Header() } items(data) { item -> PhotoItem(item) } item { Footer() } }
חשוב לזכור שבמקרים שבהם אתם מניחים פריסות כיוונים שונות,
לדוגמה, תבנית הורה שניתנת לגלילה Row
וצאצא LazyColumn
, מותרים:
Row( modifier = Modifier.horizontalScroll(scrollState) ) { LazyColumn { // ... } }
ובמקרים שבהם אתם עדיין משתמשים באותן פריסות כיוון, אבל גם הגדרתם גודל קבוע לצאצאים המקוננים:
Column( modifier = Modifier.verticalScroll(scrollState) ) { LazyColumn( modifier = Modifier.height(200.dp) ) { // ... } }
צריך להיזהר ולא להוסיף כמה רכיבים לפריט אחד
בדוגמה הזו, הפריט השני lambda פולט 2 פריטים בבלוק אחד:
LazyVerticalGrid( columns = GridCells.Adaptive(100.dp) ) { item { Item(0) } item { Item(1) Item(2) } item { Item(3) } // ... }
פריסות עצלות יטפלו בזה כצפוי – הן יתפרסו את הרכיב הראשון אחרי שיחה אחרת, כאילו היו פריטים שונים. עם זאת, יש לאיות בעיות.
כשנשלחים כמה רכיבים כחלק מפריט אחד, ההתייחסות אליהם היא בתור
ישות אחת, כלומר כבר לא ניתן להרכיב אותה בנפרד. אם רוצים
הופך לגלוי במסך, ואז כל הרכיבים התואמים
צריך להרכיב ולמדוד. השימוש בה עשוי לפגוע בביצועים
באופן מוגזם. במקרה הקיצוני של הכנסת כל הרכיבים לפריט אחד,
מבטלת לחלוטין את המטרה של שימוש בפריסות Lazy. מלבד הפוטנציאל
בעיות בביצועים. גם הוספה של יותר רכיבים לפריט אחד תפריע להם.
עם scrollToItem()
ועם animateScrollToItem()
.
עם זאת, יש תרחישים לדוגמה תקינים להצבת רכיבים מרובים בפריט אחד, כמו להציב מחיצות בתוך רשימה. אינך רוצה שהקווים יגרמו לשינוי הגלילה של מדדים, כי הם לא אמורים להיחשב כרכיבים עצמאיים. כמו כן, ביצועים לא יושפעו, מכיוון שהמפרידים קטנים. סביר להניח שיהיה צורך במחיצה גלויים כשהפריט לפניו גלוי, כך שהם יכולים להיות חלק מהפריט הקודם item:
LazyVerticalGrid( columns = GridCells.Adaptive(100.dp) ) { item { Item(0) } item { Item(1) Divider() } item { Item(2) } // ... }
מומלץ להשתמש בסידורים מותאמים אישית
בדרך כלל, רשימות עצמאות כוללות פריטים רבים, והן תופסות יותר מגודל מאגר גלילה. עם זאת, כשהרשימה מכילה מעט פריטים, יכולות להיות דרישות ספציפיות יותר לגבי האופן שבו צריך למקם אותן באזור התצוגה.
כדי לעשות זאת, אפשר להשתמש בתעשייה מותאמת אישית
Arrangement
ומעבירים את הקלט לLazyColumn
. בדוגמה הבאה, הפרמטר TopWithFooter
לאובייקט צריך ליישם רק את השיטה arrange
. קודם כל, הוא ימוקם
פריטים אחד אחרי השני. השנייה, אם הגובה הכולל של השימוש נמוך
גובה אזור התצוגה ימוקם את הכותרת התחתונה בתחתית המסך:
object TopWithFooter : Arrangement.Vertical { override fun Density.arrange( totalSize: Int, sizes: IntArray, outPositions: IntArray ) { var y = 0 sizes.forEachIndexed { index, size -> outPositions[index] = y y += size } if (y < totalSize) { val lastIndex = outPositions.lastIndex outPositions[lastIndex] = totalSize - sizes.last() } } }
כדאי להוסיף את contentType
נתחיל עם 'פיתוח נייטיב' 1.2, כדי למקסם את הביצועים של התכונה
פריסה, כדאי להוסיף
contentType
לרשימות או לתצוגות רשת. כך אפשר לציין את סוג התוכן של כל סוג
פריט בפריסה, במקרים שבהם כותבים רשימה או רשת
של כמה סוגים שונים של פריטים:
LazyColumn { items(elements, contentType = { it.type }) { // ... } }
כשמציינים
contentType
אפשר להשתמש בניסוח האוטומטי רק ביצירות מוזיקליות
בין פריטים מאותו סוג. שימוש חוזר יעיל יותר
הרכב פריטים בעלי מבנה דומה, ולספק את סוגי התוכן כדי להבטיח
התכונה 'פיתוח נייטיב' לא מנסה להרכיב פריט מסוג A בנוסף
פריט שונה מסוג B. כך אפשר למקסם את היתרונות של הרכבה
שימוש חוזר וביצועי פריסה עילית.
מדידת ביצועים
אפשר למדוד בצורה אמינה את הביצועים של פריסה מושהית רק בזמן הרצה במצב הפצה ועם אופטימיזציית R8 מופעלת. בגרסאות build של ניפוי באגים, פריסה מדורגת ייתכן שהגלילה תופיע לאט יותר. כדי לקבל מידע נוסף בנושא, אפשר לעיין ביצועי הכתיבה.
מומלץ עבורך
- הערה: טקסט הקישור מוצג כאשר JavaScript מושבת
- העברה של
RecyclerView
לרשימת העצלנים - שמירת המצב של ממשק המשתמש בחלונית הכתיבה
- Kotlin ל-Jetpack פיתוח נייטיב