รายการแบบ Lazy ในตารางกริด

ไอคอนคะแนน 4 ดาว

Composable Grid จะสร้างเลย์เอาต์หน้าจอแบบ 2 มิติเชิงโครงสร้าง Grid กำหนดโครงสร้างเลย์เอาต์ที่ตอบสนองโดยใช้แทร็ก (แถวและคอลัมน์) และช่องว่างที่กำหนดไว้อย่างชัดเจนเป็นสถาปัตยกรรมพื้นฐานของ UI

เนื่องจาก Grid เป็นคอนเทนเนอร์เชิงโครงสร้างมากกว่าคอนเทนเนอร์ที่โหลดแบบ Lazy Loading คุณจึงต้อง กำหนดองค์ประกอบทุกรายการที่วางไว้ภายในอย่างชัดเจนโดยไม่ต้องรีไซเคิลรายการเมื่อเลื่อน ด้วยเหตุนี้ การแสดงผลชุดข้อมูลขนาดใหญ่หรือชุดข้อมูลแบบไดนามิกภายใน Grid โดยตรงอาจทำให้เกิดปัญหาคอขวดด้านประสิทธิภาพ เนื่องจากรายการทั้งหมดจะประกอบพร้อมกัน

หากต้องการแสดงคอลเล็กชันข้อมูลขนาดใหญ่ภายในเลย์เอาต์หน้าจอที่มีโครงสร้าง ให้ฝังคอมโพเนนต์แบบเลซี เช่น LazyColumn หรือ LazyRow ในเซลล์ Grid แต่โปรดทราบว่าแทร็กที่ยืดหยุ่น (ที่มีข้อกำหนด เช่น 1.fr) จะค้นหาขนาดที่แท้จริงขององค์ประกอบย่อย เนื่องจาก SubcomposeLayout ไม่รองรับการส่งผ่านการวัดผลโดยธรรมชาติ การวางรายการแบบ Lazy ไว้ในแทร็กที่ยืดหยุ่นจะทําให้เกิดข้อขัดข้อง IllegalStateException หากต้องการวางรายการแบบเลื่อนอย่างปลอดภัยภายในแทร็กกริดที่ยืดหยุ่น ได้ คุณต้องใช้การกำหนดขนาด GridTrackSize.MinMax (เช่น minmax(0.dp, 1.fr)) เพื่อข้ามการวัดค่าโดยธรรมชาติ

เลย์เอาต์หน้าจอที่มีส่วนหัวด้านบน รายการที่เลื่อนได้ในพื้นที่เนื้อหาหลัก และส่วนท้ายด้านล่าง
รูปที่ 1 เลย์เอาต์หน้าจอเชิงโครงสร้างที่มีส่วนหัว ส่วนท้าย และLazyColumnที่ฝังไว้สำหรับเนื้อหา

แนวทางปฏิบัติแนะนำ

  • ใช้รายการแบบเลซี่แทนลูปขนาดใหญ่ที่ชัดเจน: หากต้องการแสดงชุดข้อมูลขนาดใหญ่หรือชุดข้อมูลแบบไดนามิกภายใน Grid ที่มีโครงสร้าง ให้ฝังคอมโพเนนต์แบบเลซี่ (โดยปกติคือ LazyColumn หรือ LazyRow) ไว้ในเซลล์ตารางกริดที่เฉพาะเจาะจงแทนการสร้างลูปขนาดใหญ่ที่ชัดเจนในรายการ เนื่องจาก Grid ไม่รีไซเคิลรายการและมีขีดจำกัดที่ 1,000 แทร็ก
  • ใช้ MinMax track sizing for lazy lists: เนื่องจาก LazyColumn และ LazyRow ไม่รองรับการวัดค่าที่แท้จริง (ดู SubcomposeLayout) ให้ใช้ GridTrackSize.MinMax ในแทร็กที่ยืดหยุ่นซึ่งโฮสต์คอมโพเนนต์แบบเลซีเพื่อข้าม การวัดค่าที่แท้จริงอย่างปลอดภัย

ส่วนผสม

  • Grid: เลย์เอาต์ที่ประกอบได้ซึ่งวางรายการในโครงสร้างตารางกริดแบบ 2 มิติ ที่กำหนดค่าโดยใช้แทร็กแถวและคอลัมน์ที่ชัดเจน
  • LazyColumn: รายการที่เลื่อนในแนวตั้งซึ่งประกอบและนำกลับมาใช้ใหม่เฉพาะ รายการที่มองเห็นได้บนหน้าจอในขณะนั้น
  • GridTrackSize.MinMax: ติดตามพร็อพเพอร์ตี้การปรับขนาดที่กำหนดขอบเขตที่ยืดหยุ่น (min และ max) เพื่อโฮสต์คอมโพเนนต์ที่โหลดแบบ Lazy อย่างปลอดภัยโดยไม่ทำให้เกิดข้อขัดข้องในการวัดรันไทม์
  • gridItem: เขียนส่วนขยาย Modifier ที่กำหนดองค์ประกอบ UI ย่อยให้กับเซลล์หรือพื้นที่ที่มีชื่อเฉพาะภายใน Grid

ขั้นตอน

จัดโครงสร้างเลย์เอาต์หน้าจอโดยกำหนดตัวระบุพื้นที่เชิงความหมาย กำหนดค่า แทร็กกริดด้วยminmaxการกำหนดขนาดเพื่อความเข้ากันได้ของรายการแบบเลื่อน และฝัง LazyColumnภายในพื้นที่เนื้อหากริด

1. กำหนดค่าแทร็กตารางกริดและพื้นที่ที่มีชื่อ

สร้างenumคลาสเพื่อแสดงถึงภูมิภาคที่แตกต่างกันของเลย์เอาต์หน้าจอ และกำหนดGridConfigurationScope Lambda สำหรับแทร็กเลย์เอาต์และพื้นที่ที่มีชื่อ ใช้ GridTrackSize.MaxContent สำหรับแถวส่วนหัวและส่วนท้ายเพื่อให้พอดีกับขนาดเนื้อหา และใช้ minmax(0.dp, 1.fr) สำหรับแทร็กเนื้อหาที่โฮสต์รายการแบบ Lazy Loading เพื่อจัดสรรพื้นที่ที่ยืดหยุ่นได้โดยไม่ต้องค้นหาการวัดค่าภายในที่ไม่รองรับ

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. วางคอมโพเนนต์แบบคงที่ในตารางกริด

ใน Composable ให้ส่ง lazyConfig ไปยังคอนเทนเนอร์ Grid ภายในcontent lambda ให้วางคอมโพเนนต์แบบคงที่ (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))
            }
        }
    }
}

ผลลัพธ์

เลย์เอาต์หน้าจอของคุณใช้ Grid API เพื่อกำหนดโครงสร้างหน้าเว็บแบบ 2 มิติโดยรวม ในขณะที่ฝัง LazyColumn ในแทร็กที่ยืดหยุ่น พร้อมการกำหนดขนาด minmax เพื่อรีไซเคิลรายการได้อย่างมีประสิทธิภาพและหลีกเลี่ยงข้อยกเว้นขณะรันไทม์

แหล่งข้อมูลเพิ่มเติม