LazyColumn เป็นฟังก์ชัน composable ใน Jetpack Compose สำหรับสร้างรายการแนวตั้งที่มีการโหลดองค์ประกอบแบบขี้เกียจ แตกต่างจาก Column ตรงที่ LazyColumn จะสร้างและประกอบเฉพาะองค์ประกอบที่มองเห็นบนหน้าจอ และนำกลับมาใช้ใหม่เมื่อเลื่อน ตาม Google Android Documentation, 2025 LazyColumn เป็นเครื่องมือหลักสำหรับการแสดงชุดข้อมูลขนาดใหญ่ในแอปพลิเคชันมือถือด้วยการจัดการหน่วยความจำที่มีประสิทธิภาพ
ประเด็นสำคัญ
LazyColumn เป็นฟังก์ชัน composable ที่ใช้รายการแนวตั้งที่เลื่อนได้พร้อมการโหลดแบบขี้เกียจ แตกต่างจาก Column ที่แสดงผลองค์ประกอบย่อยทั้งหมดพร้อมกัน LazyColumn จะสร้างเฉพาะองค์ประกอบที่อยู่ในพื้นที่มองเห็นเท่านั้น
กลไกการโหลดแบบขี้เกียจใน LazyColumn ขึ้นอยู่กับการนำองค์ประกอบกลับมาใช้ใหม่: เมื่อองค์ประกอบถูกซ่อนระหว่างการเลื่อน องค์ประกอบและเลย์เอาต์ของมันสามารถนำกลับมาใช้ใหม่สำหรับองค์ประกอบใหม่ที่แสดง ซึ่งช่วยประหยัดหน่วยความจำและเวลา CPU โดยเฉพาะในรายการยาว
ตาม Android Developers Blog, 2024 LazyColumn สามารถจัดการรายการที่มีองค์ประกอบนับหมื่นได้อย่างมีประสิทธิภาพโดยไม่ทำให้ประสิทธิภาพลดลงอย่างมีนัยสำคัญ แต่ละองค์ประกอบใน LazyColumn มีคีย์ (key) ที่ช่วยให้ Compose ระบุและรักษาสถานะขององค์ประกอบเมื่อรายการเปลี่ยนแปลง
LazyColumn รับพารามิเตอร์ modifier, state, contentPadding, reverseLayout, verticalArrangement และ horizontalAlignment เนื้อหาถูกกำหนดในบล็อก lambda ผ่านฟังก์ชัน DSL items และ item
@Composable
fun SimpleLazyColumn() {
val itemsList = (1..100).toList()
LazyColumn(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(16.dp)
) {
items(itemsList) { item ->
Text(text = "รายการ $item")
}
}
}
บล็อก DSL ของ LazyColumn มีฟังก์ชัน items และ item สำหรับเพิ่มเนื้อหา items รับชุดข้อมูล คีย์ และฟังก์ชันโรงงานเพื่อสร้างองค์ประกอบ item เพิ่มองค์ประกอบคงที่เดี่ยวลงในรายการ
itemsIndexed เป็นรูปแบบหนึ่งของ items ที่ส่งดัชนีองค์ประกอบนอกเหนือจากข้อมูล ซึ่งมีประโยชน์เมื่อคุณต้องการทราบตำแหน่งขององค์ประกอบโดยไม่ต้องคำนวณแยกต่างหาก items(size) รับเฉพาะจำนวนองค์ประกอบและโรงงานโดยไม่ผูกกับชุดข้อมูล
พารามิเตอร์ key ใน items ระบุแต่ละองค์ประกอบโดยเฉพาะ ตาม Material Design Guidelines, 2025 คีย์ช่วยปรับปรุงประสิทธิภาพเมื่ออัปเดตและเคลื่อนไหวองค์ประกอบ เนื่องจาก Compose สามารถติดตามการเคลื่อนไหวหรือการเปลี่ยนแปลงขององค์ประกอบเฉพาะด้วยคีย์ของมัน
ฟังก์ชัน items ที่มี contentType ช่วยให้ LazyColumn เพิ่มประสิทธิภาพการนำองค์ประกอบประเภทต่าง ๆ กลับมาใช้ใหม่ ในตัวอย่างด้านล่างนี้ มีการใช้หัวข้อส่วนและแถวปกติในรายการเดียว
@Composable
fun MixedItemsList() {
LazyColumn {
item {
Text(
text = "หัวข้อ",
style = MaterialTheme.typography.headlineMedium
)
}
items(
items = (1..20).toList(),
key = { it },
contentType = { "item" }
) { item ->
Text(text = "แถว $item")
}
}
}
LazyListState เป็นออบเจกต์สถานะของ LazyColumn ที่ติดตามตำแหน่งการเลื่อนปัจจุบัน องค์ประกอบที่มองเห็นแรก และออฟเซ็ต สามารถสร้างได้ผ่าน rememberLazyListState() และส่งต่อไปยังพารามิเตอร์ state ของ LazyColumn
LazyListState มีเมธอด animateScrollToItem และ scrollToItem สำหรับการเลื่อนโดยโปรแกรมไปยังองค์ประกอบเฉพาะ animateScrollToItem สร้างแอนิเมชันการเลื่อนที่ราบรื่น ในขณะที่ scrollToItem เลื่อนทันที ทั้งสองเมธอดต้องการการเรียกภายใน coroutine ใน CompositionContext
ตาม Android Developers, 2024 LazyListState ยังมี layoutInfo ซึ่งให้ข้อมูลเกี่ยวกับองค์ประกอบที่มองเห็น — ดัชนี ออฟเซ็ต และขนาดของมัน ซึ่งมีประโยชน์สำหรับการใช้งานวิเคราะห์ การติดตามการดู หรือการเลื่อนแบบไม่สิ้นสุด
ในตัวอย่างนี้ LazyColumn ถูกควบคุมผ่าน LazyListState ปุ่มจะเลื่อนรายการไปยังองค์ประกอบที่มีดัชนี 50 ด้วยแอนิเมชันที่ราบรื่น
@Composable
fun ScrollableList() {
val listState = rememberLazyListState()
val scope = rememberCoroutineScope()
Column {
Button(
onClick = {
scope.launch {
listState.animateScrollToItem(50)
}
}
) {
Text("เลื่อนไปที่ 50")
}
LazyColumn(state = listState) {
items((1..100).toList()) { item ->
Text(
text = "รายการ $item",
modifier = Modifier.padding(8.dp)
)
}
}
}
}
ปัจจัยประสิทธิภาพหลักของ LazyColumn คือการใช้คีย์อย่างถูกต้อง แต่ละองค์ประกอบควรมีคีย์ที่เสถียรและไม่ซ้ำกันผ่านพารามิเตอร์ key หากไม่มีคีย์ Compose จะไม่สามารถนำองค์ประกอบกลับมาใช้ใหม่ได้อย่างถูกต้องเมื่อข้อมูลเปลี่ยนแปลง ซึ่งนำไปสู่การประกอบใหม่
contentType บอก LazyColumn ว่าองค์ประกอบใดมีประเภทเลย์เอาต์เดียวกัน เมื่อสององค์ประกอบที่มี contentType เดียวกันเข้าสู่พูลรีไซเคิล LazyColumn สามารถนำเลย์เอาต์ของพวกมันกลับมาใช้ใหม่ได้โดยไม่ต้องประกอบใหม่ ตาม Android Developers Blog, 2024 contentType ช่วยปรับปรุงประสิทธิภาพ 30–50% ในรายการที่มีประเภทองค์ประกอบแตกต่างกัน
สำหรับ LazyColumn การหลีกเลี่ยงพารามิเตอร์ที่ไม่เสถียรในฟังก์ชันโรงงานก็สำคัญเช่นกัน ทุกครั้งที่พารามิเตอร์องค์ประกอบเปลี่ยนแปลง Compose จะประกอบองค์ประกอบนั้นใหม่ การใช้ remember และ derivedStateOf สำหรับค่าที่เสถียรช่วยลดจำนวนการประกอบใหม่
| ปัจจัย | ผลกระทบ | คำแนะนำ |
|---|---|---|
| คีย์ (key) | สำคัญ | ตั้งค่า key ที่เสถียรและไม่ซ้ำกันสำหรับ items เสมอ |
| contentType | มีนัยสำคัญ | ระบุประเภทองค์ประกอบเพื่อเพิ่มประสิทธิภาพการนำกลับมาใช้ใหม่ |
| ขนาดองค์ประกอบ | ปานกลาง | ใช้ขนาดคงที่เมื่อเป็นไปได้ |
| รายการซ้อน | สำคัญ | หลีกเลี่ยง LazyColumn ภายใน LazyColumn — ใช้ LazyVerticalGrid |
stickyHeader เป็นฟังก์ชัน DSL ของ LazyColumn ที่ยึดหัวข้อส่วนไว้ที่ด้านบนของรายการเมื่อเลื่อน เมื่อส่วนถัดไปถึงด้านบน หัวข้อของมันจะแทนที่หัวข้อปัจจุบัน พฤติกรรมนี้คุ้นเคยสำหรับผู้ใช้จากรายชื่อผู้ติดต่อและปฏิทิน
stickyHeader รับคีย์และฟังก์ชันโรงงาน คล้ายกับ item แตกต่างจาก item ทั่วไป ตรงที่ stickyHeader ยังคงมองเห็นได้ขณะเลื่อนผ่านเนื้อหาของส่วนของมัน เมื่อส่วนถูกเลื่อนจนหมด หัวข้อของส่วนถัดไปจะดันหัวข้อก่อนหน้าออกไป
ตาม Material Design Guidelines, 2025 sticky header ช่วยปรับปรุงการนำทางในรายการยาวและลดภาระทางปัญญาของผู้ใช้ ในการใช้ sticky header เพียงห่อหัวข้อส่วนใน stickyHeader ในตำแหน่งที่ถูกต้องสัมพันธ์กับองค์ประกอบ items
@Composable
fun SectionedList(sections: Map<String, List<String>>) {
LazyColumn {
sections.forEach { (header, items) ->
stickyHeader {
Text(
text = header,
modifier = Modifier.background(Color.White)
.padding(16.dp)
)
}
items(items) { item ->
Text(text = item, modifier = Modifier.padding(8.dp))
}
}
}
}
คำถามที่พบบ่อย
Column แสดงผลองค์ประกอบทั้งหมดพร้อมกันและเหมาะสำหรับรายการสูงสุด 20–30 องค์ประกอบ LazyColumn สร้างเฉพาะองค์ประกอบที่มองเห็นและนำกลับมาใช้ใหม่เมื่อเลื่อน ทำให้คุณทำงานกับองค์ประกอบนับพันได้โดยไม่สูญเสียประสิทธิภาพ
ใช้ Arrangement.spacedBy ในพารามิเตอร์ verticalArrangement หรือฟังก์ชัน items ที่มีตัวคั่นผ่านดัชนี สำหรับตัวคั่นที่ซับซ้อน ให้เพิ่ม item แยกต่างหากที่มี Divider() ระหว่างองค์ประกอบรายการ
LazyColumn จะประกอบใหม่โดยอัตโนมัติเมื่อชุดข้อมูลเปลี่ยนแปลง หากใช้คีย์ที่เสถียร การเปลี่ยนแปลงข้อมูลที่ตรวจพบผ่าน mutableStateListOf หรือ StateFlow ทำให้เฉพาะองค์ประกอบที่เปลี่ยนแปลงถูกวาดใหม่
ไม่แนะนำให้ซ้อน LazyColumn โดยตรงภายใน LazyColumn — ทั้งสองมีการเลื่อนอิสระ ซึ่งสร้างความขัดแย้งของท่าทาง ให้ใช้ Column ปกติกับ LazyColumn ภายใน Section ที่เลื่อนได้หรือ LazyVerticalGrid สำหรับกริดแทน
ใช้ LazyListState.layoutInfo.visibleItemsInfo และเปรียบเทียบดัชนีขององค์ประกอบที่มองเห็นสุดท้ายกับจำนวนองค์ประกอบทั้งหมด สำหรับการเลื่อนแบบไม่สิ้นสุด ให้ติดตามเมื่อองค์ประกอบที่มองเห็นสุดท้ายเข้าใกล้จุดสิ้นสุดของรายการ
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม