רשימות עצלניות בפריסת רשת

סמל של דירוג ארבעה כוכבים

הפונקציה הקומפוזבילית Grid יוצרת פריסות מסך מבניות דו-ממדיות. הרכיב Grid מגדיר מבנה פריסה רספונסיבי באמצעות מסלולים (שורות ועמודות) ומרווחים שמוגדרים באופן מפורש, כארכיטקטורה הבסיסית של ממשק המשתמש.

מכיוון ש-Grid הוא קונטיינר מבני ולא קונטיינר של טעינה מדורגת, צריך להגדיר באופן מפורש כל רכיב שמוצב בתוכו בלי למחזר פריטים בגלילה. לכן, עיבוד של קבוצות נתונים גדולות או דינמיות ישירות בתוך Grid יכול לגרום לצווארי בקבוק בביצועים, כי כל הפריטים נוצרים בו-זמנית.

כדי להציג אוספים גדולים של נתונים בפריסת מסך מובנית, מטמיעים רכיבים בטעינה מדורגת כמו LazyColumn או LazyRow בתאי Grid. אבל שימו לב: מסלולים גמישים (עם מפרטים כמו 1.fr) שולחים שאילתות לגבי הגדלים הפנימיים של רכיבי הצאצא. מכיוון ש-SubcomposeLayout לא תומך במעברי מדידה פנימיים, הצבת רשימה עם טעינה מדורגת בתוך מסלול גמיש גורמת לקריסה של IllegalStateException. כדי למקם בבטחה רשימות בטעינה מדורגת בתוך מסלול גמיש של רשת, צריך להשתמש בגודל GridTrackSize.MinMax (כמו minmax(0.dp, 1.fr)) כדי לעקוף את שלב המדידה הפנימית.

פריסת מסך עם כותרת עליונה, רשימת פריטים שאפשר לגלול באזור התוכן הראשי וכותרת תחתונה.
איור 1. פריסת מסך מבנית עם כותרת עליונה, כותרת תחתונה ו-LazyColumn מוטמע לתוכן.

שיטות מומלצות

  • שימוש ברשימות עם טעינה מדורגת במקום בלולאות גדולות ומפורשות: כדי להציג קבוצות נתונים גדולות או דינמיות בתוך Grid מובנה, כדאי להטמיע רכיבים עם טעינה מדורגת (בדרך כלל LazyColumn או LazyRow) בתוך תאים ספציפיים ברשת, במקום ליצור לולאות גדולות ומפורשות על פריטים, כי Grid לא ממחזר פריטים ויש לו מגבלה של 1,000 טראקים.
  • שימוש בגודל טראק של MinMax לרשימות בטעינה מדורגת: מכיוון ש-LazyColumn ו-LazyRow לא תומכים במעברי מדידה פנימיים (ראו SubcomposeLayout), צריך להשתמש ב-GridTrackSize.MinMax בטראקים גמישים שמארחים רכיבים בטעינה מדורגת כדי לעקוף מדידות פנימיות באופן בטוח.

אלמנטים

  • ‫Grid: פריסה קומפוזבילית שמציבה פריטים במבנה רשת דו-ממדי שמוגדר באמצעות מסלולים מפורשים של שורות ועמודות.
  • ‫LazyColumn: רשימה עם גלילה אנכית שיוצרת וממחזרת רק את הפריטים שמוצגים כרגע במסך.
  • ‫GridTrackSize.MinMax: מאפיין למעקב אחרי גודל שמגדיר גבולות גמישים (min ו-max) כדי לארח באופן בטוח רכיבים בטעינה מדורגת בלי לגרום לקריסות של מדידות בזמן הריצה.
  • gridItem: תוסף של Compose Modifier שמקצה רכיב בממשק המשתמש לתא ספציפי או לאזור עם שם בתוך Grid.

צעדים

כדי להגדיר את פריסת המסך, מגדירים מזהי אזורים סמנטיים, מגדירים את מסלולי הרשת עם גודל minmax לתאימות עם רשימה בטעינה מדורגת, ומטמיעים את LazyColumn בתוך אזור התוכן של הרשת.

1. הגדרת שורות ואזורים עם שמות ברשת

יוצרים מחלקה מסוג enum כדי לייצג את האזורים השונים בפריסת המסך, ומגדירים למבדה מסוג GridConfigurationScope למסלולי הפריסה ולאזורים עם השמות. משתמשים ב-GridTrackSize.MaxContent בשורות של הכותרת העליונה והכותרת התחתונה כדי להתאים את מידות התוכן שלהן, ומשתמשים ב-minmax(0.dp, 1.fr) למסלול התוכן שמארח את הרשימה בטעינה מדורגת כדי להקצות מקום גמיש בלי לשלוח שאילתות לגבי מידות פנימיות שלא נתמכות:

enum class ScreenArea {
    Header,
    Content,
    Footer
}


val lazyConfig: GridConfigurationScope.() -> Unit = {
    column(minmax(0.dp, 1.fr))
    row(GridTrackSize.MaxContent)
    row(minmax(0.dp, 1.fr))
    row(GridTrackSize.MaxContent)

    area(ScreenArea.Header, row = 1, column = 1)
    area(ScreenArea.Content, row = 2, column = 1)
    area(ScreenArea.Footer, row = 3, column = 1)
    gap(8.dp)
}

2. הצבת רכיבים סטטיים ברשת

בפונקציה הקומפוזבילית, מעבירים את lazyConfig לקונטיינר Grid. בתוך פונקציית הלמבדה content, ממקמים רכיבים סטטיים (Header ו-Footer) ומגדירים את המיקום שלהם באמצעות Modifier.gridItem() עם מזהי האזורים המתאימים.

3. הטמעת LazyColumn באזור התוכן

בתא התוכן, מטמיעים את LazyColumn באמצעות Modifier.gridItem(ScreenArea.Content). מכיוון שהמסלול של התוכן הוגדר עם minmax(0.dp, 1.fr) בשלב 1, LazyColumn יכול למדוד ולמחזר פריטים בבטחה בזמן הגלילה בלי לשלוח שאילתות לגבי מאפיינים פנימיים לא נתמכים:

@Composable
fun GridWithLazyColumn(
    modifier: Modifier = Modifier,
    items: List<String> = emptyList(),
) {
    Grid(
        modifier = modifier.fillMaxSize(),
        config = lazyConfig
    ) {
        Text("Header", Modifier.gridItem(ScreenArea.Header).padding(16.dp))
        Text("Footer", Modifier.gridItem(ScreenArea.Footer).padding(16.dp))

        // LazyColumn placed in the content area for large datasets
        LazyColumn(
            modifier = Modifier
                .gridItem(ScreenArea.Content)
                .fillMaxSize(),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            items(items) { item ->
                Text(item, Modifier.padding(16.dp))
            }
        }
    }
}

תוצאות

עכשיו פריסת המסך משתמשת ב-API של Grid כדי להגדיר את המבנה הדו-ממדי הכולל של הדף, תוך הטמעת LazyColumn במסלול גמיש עם שינוי גודל של minmax כדי למחזר פריטים ברשימה ביעילות ולמנוע חריגות בזמן הריצה.

מקורות מידע נוספים