การแบ่งหน้าในรายการ Compose
แสดงผลข้อมูลแบบแบ่งหน้าด้วย LazyColumn
การแบ่งหน้าในรายการ Compose เป็นบทเรียน Android Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Android Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน
การแสดงข้อมูลแบบแบ่งหน้าใน Compose
ชั้นข้อมูลส่งมอบ Flow<PagingData<Article>> ให้คุณ ไลบรารี paging-compose จะแปลงโฟลว์นี้เป็นสิ่งที่ LazyColumn แสดงผลได้ พร้อมการโหลดตามต้องการขณะผู้ใช้เลื่อนดู
ตัวเชื่อมหลักคือ collectAsLazyPagingItems()
collectAsLazyPagingItems
เรียก collectAsLazyPagingItems() บนโฟลว์ภายในคอมโพสสิเบิล ฟังก์ชันนี้จะส่งคืนออบเจ็กต์ LazyPagingItems ซึ่งติดตามรายการที่โหลดแล้วและสถานะการโหลด พร้อมจัดองค์ประกอบ UI ใหม่เมื่อมีหน้าเข้ามา
import androidx.paging.compose.collectAsLazyPagingItems
@Composable
fun ArticleScreen(viewModel: ArticleViewModel) {
val articles = viewModel.articles.collectAsLazyPagingItems()
ArticleList(articles)
}items() กับ LazyPagingItems
ภายใน LazyColumn ให้ใช้โอเวอร์โหลด items() ของ Paging ซึ่งจะอ่านข้อมูลจาก LazyPagingItems และเรียกโหลดหน้าถัดไปเมื่อผู้ใช้เลื่อนเข้าใกล้ท้ายรายการ
รายการแต่ละรายการอาจเป็น null เมื่อเปิดใช้ตัวแทน ดังนั้นต้องจัดการกรณีนี้ด้วย
import androidx.compose.foundation.lazy.LazyColumn
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.items
@Composable
fun ArticleList(articles: LazyPagingItems<Article>) {
LazyColumn {
items(articles) { article ->
if (article != null) {
ArticleRow(article)
}
}
}
}คีย์ที่คงที่สำหรับรายการ
กำหนดคีย์ที่คงที่ให้แต่ละแถว เพื่อให้ Compose ติดตามรายการข้ามการโหลดหน้าได้อย่างมีประสิทธิภาพ และหลีกเลี่ยงการจัดองค์ประกอบใหม่โดยไม่จำเป็น
ใช้ตัวช่วย itemKey ของ Paging กับคุณสมบัติที่ไม่ซ้ำและคงที่ เช่น รหัสของรายการ
import androidx.paging.compose.itemKey
LazyColumn {
items(
count = articles.itemCount,
key = articles.itemKey { it.id }
) { index ->
val article = articles[index]
if (article != null) ArticleRow(article)
}
}การอ่านสถานะการโหลด
LazyPagingItems.loadState เปิดเผยสถานะการโหลดและข้อผิดพลาดปัจจุบันสำหรับการดำเนินการสามประเภท:
refresh- การโหลดครั้งแรกหรือการโหลดจากการดึงเพื่อรีเฟรชappend- การโหลดหน้าถัดไป (เลื่อนลง)prepend- การโหลดหน้าก่อนหน้า (เลื่อนขึ้น)
import androidx.paging.LoadState
val refresh = articles.loadState.refresh
val append = articles.loadState.append
val isInitialLoading = refresh is LoadState.Loading
val isLoadingMore = append is LoadState.Loadingสถานะกำลังโหลดและว่างเปล่าแบบเต็มหน้าจอ
ใช้สถานะ refresh เพื่อควบคุมการแสดงผลครั้งแรก: แสดงตัวหมุนตรงกลางระหว่างโหลด แสดงหน้าข้อผิดพลาดเมื่อโหลดไม่สำเร็จ หรือแสดงข้อความว่างเปล่าเมื่อไม่มีอะไรให้แสดง
when (val refresh = articles.loadState.refresh) {
is LoadState.Loading -> FullScreenSpinner()
is LoadState.Error -> FullScreenError(
message = refresh.error.message,
onRetry = { articles.retry() }
)
is LoadState.NotLoading -> {
if (articles.itemCount == 0) EmptyState()
else ArticleList(articles)
}
}ตัวหมุนท้ายรายการขณะเพิ่มข้อมูล
หากต้องการแสดงตัวหมุนขนาดเล็กด้านล่างขณะโหลดหน้าถัดไป ให้เพิ่มรายการพิเศษใน LazyColumn ตามสถานะการโหลด append
LazyColumn {
items(count = articles.itemCount, key = articles.itemKey { it.id }) { index ->
articles[index]?.let { ArticleRow(it) }
}
if (articles.loadState.append is LoadState.Loading) {
item {
Box(Modifier.fillMaxWidth().padding(16.dp), Alignment.Center) {
CircularProgressIndicator()
}
}
}
}ลองใหม่เมื่อเกิดข้อผิดพลาด
เมื่อการเพิ่มข้อมูลไม่สำเร็จ ให้แสดงแถวลองใหม่ที่ด้านล่าง การเรียก articles.retry() จะลองโหลดที่ล้มเหลวอีกครั้งเท่านั้น ไม่ได้โหลดรายการทั้งหมดใหม่
val append = articles.loadState.append
if (append is LoadState.Error) {
item {
Row(Modifier.fillMaxWidth().padding(16.dp), Arrangement.Center) {
Text("Couldn't load more")
Spacer(Modifier.width(8.dp))
Button(onClick = { articles.retry() }) { Text("Retry") }
}
}
}ดึงเพื่อรีเฟรช
เรียกใช้การโหลดใหม่ด้วย articles.refresh() และใช้ร่วมกับการดึงเพื่อรีเฟรชของ Material 3 โดยควบคุมตัวบ่งชี้จากสถานะการโหลด refresh
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
val isRefreshing = articles.loadState.refresh is LoadState.Loading
PullToRefreshBox(
isRefreshing = isRefreshing,
onRefresh = { articles.refresh() }
) {
ArticleList(articles)
}ส่วนหัวและตัวคั่น
คุณสามารถผสมรายการแบบแบ่งหน้ากับเนื้อหาที่ไม่ได้แบ่งหน้าใน LazyColumn เดียวกันได้อย่างอิสระ เพิ่มส่วนหัวแบบติดอยู่กับที่ แถบค้นหา หรือตัวคั่นส่วนต่าง ๆ รอบการเรียก items() แบบแบ่งหน้า
เนื่องจากทุกอย่างอยู่ใน LazyColumn เดียวกัน การเลื่อนจึงเป็นหนึ่งเดียวและลื่นไหล
LazyColumn {
item { SearchBar(query, onQueryChange) }
items(count = articles.itemCount, key = articles.itemKey { it.id }) { index ->
val article = articles[index]
if (article != null) {
ArticleRow(article)
HorizontalDivider()
}
}
if (articles.loadState.append.endOfPaginationReached) {
item { Text("You're all caught up", Modifier.padding(16.dp)) }
}
}ดูตัวอย่างรายการแบบแบ่งหน้า
สำหรับตัวอย่าง Compose และการทดสอบ คุณไม่จำเป็นต้องใช้เครือข่ายจริง ให้ห่อข้อมูลตัวอย่างด้วย PagingData.from(...) และเปิดเผยข้อมูลนั้นเป็นโฟลว์
วิธีนี้ช่วยให้คุณสร้างและดูตัวอย่าง UI ของรายการแยกจากส่วนอื่นได้
import androidx.paging.PagingData
import kotlinx.coroutines.flow.flowOf
@Preview
@Composable
fun ArticleListPreview() {
val sample = listOf(Article(1, "Hello"), Article(2, "World"))
val flow = flowOf(PagingData.from(sample))
ArticleList(flow.collectAsLazyPagingItems())
}ตรวจสอบความเข้าใจ
ฟังก์ชันใดแปลง Flow<PagingData> ให้เป็นสิ่งที่ LazyColumn ของ Compose แสดงผลได้
สรุป: Paging ใน Compose
คุณได้แสดงข้อมูลแบบแบ่งหน้าใน Jetpack Compose แล้ว:
collectAsLazyPagingItems()เชื่อมโฟลว์เข้ากับ UI- โอเวอร์โหลด
items()ของ Paging จะโหลดข้อมูลเพิ่มขณะเลื่อนดู และต้องจัดการตัวแทนที่เป็นnull - ใช้
itemKey { it.id }สำหรับคีย์ที่คงที่ loadState.refresh/append/prependใช้ควบคุมตัวหมุน ข้อผิดพลาด และสถานะว่างเปล่าretry()และrefresh()ใช้กู้คืนจากข้อผิดพลาดและโหลดข้อมูลใหม่
ถัดไป: การรวมเครือข่ายและฐานข้อมูลด้วย RemoteMediator
คำถามที่พบบ่อย
บทเรียน “การแบ่งหน้าในรายการ Compose” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การแบ่งหน้าในรายการ Compose” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Android Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การแบ่งหน้าในรายการ Compose”
แสดงผลข้อมูลแบบแบ่งหน้าด้วย LazyColumn คุณปฏิบัติ Android Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Android Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Android Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การแบ่งหน้าในรายการ Compose” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Android Academy นี้ได้ไหม
ได้ บทเรียน Android Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เหตุใดจึงต้องแบ่งหน้า
- PagingSource และ Pager
- การแบ่งหน้าในรายการ Compose
- RemoteMediator และการแคช