ย้ายไปที่หน้า 3

Paging 3 แตกต่างจากไลบรารี Paging เวอร์ชันก่อนหน้าอย่างมาก โดยเวอร์ชันนี้มีฟังก์ชันการทำงานที่ได้รับการปรับปรุง การรองรับโครูทีนและ Flow ของ Kotlin ระดับเฟิร์สคลาส รวมถึงการผสานรวมที่ราบรื่นกับ Jetpack Compose

ประโยชน์ของการย้ายข้อมูลไปยัง Paging 3

Paging 3 มีฟีเจอร์ต่อไปนี้ที่ไม่มีในไลบรารีเวอร์ชันก่อนหน้า

  • การรองรับโครูทีนและ Flow ของ Kotlin ระดับเฟิร์สคลาส
  • สถานะการโหลดและสัญญาณข้อผิดพลาดในตัวสำหรับการออกแบบ UI ที่ตอบสนอง ซึ่งรวมถึงฟังก์ชันการทำงานในการลองอีกครั้งและรีเฟรช
  • การปรับปรุงเลเยอร์ที่เก็บข้อมูล ซึ่งรวมถึงการรองรับการยกเลิกและอินเทอร์เฟซแหล่งข้อมูลที่เรียบง่ายขึ้น
  • การปรับปรุงเลเยอร์การนำเสนอ ตัวคั่นรายการ การแปลงหน้าเว็บที่กำหนดเอง ส่วนหัวและส่วนท้าย รวมถึงรายการสถานะการโหลดสำหรับรายการแบบ Lazy

ย้ายข้อมูลแอปไปยัง Paging 3

หากต้องการย้ายข้อมูลไปยัง Paging 3 อย่างสมบูรณ์ คุณต้องย้ายข้อมูลคอมโพเนนต์หลักเหล่านี้จาก Paging 2

  • คลาส DataSource
  • PagedList
  • เลเยอร์การนำเสนอ (ไปยัง LazyPagingItems)

อย่างไรก็ตาม คอมโพเนนต์บางอย่างของ Paging 3 สามารถใช้งานร่วมกับ Paging เวอร์ชันก่อนหน้าได้ โดยเฉพาะอย่างยิ่ง API Pager สามารถใช้ออบเจ็กต์ DataSource แบบเก่ากับเมธอด asPagingSourceFactory ได้ ซึ่งหมายความว่าคุณมีตัวเลือกการย้ายข้อมูลต่อไปนี้

  • คุณสามารถย้ายข้อมูล DataSource ไปยัง PagingSource แต่ปล่อยให้การใช้งาน Paging ส่วนอื่นๆ ไม่เปลี่ยนแปลง
  • คุณสามารถย้ายข้อมูลการใช้งาน Paging ทั้งหมดเพื่อย้ายข้อมูลแอปไปยัง Paging 3 อย่างสมบูรณ์

ส่วนต่างๆ ในหน้านี้จะอธิบายวิธีย้ายข้อมูลคอมโพเนนต์ Paging ในแต่ละเลเยอร์ของแอป

คลาส DataSource

ส่วนนี้อธิบายการเปลี่ยนแปลงที่จำเป็นทั้งหมดเพื่อย้ายข้อมูลการใช้งาน Paging แบบเก่าให้ใช้ PagingSource

PageKeyedDataSource, PositionalDataSource และ ItemKeyedDataSource จาก Paging 2 จะรวมกันเป็น API PagingSource ใน Paging 3 เมธอดการโหลดจากคลาส API แบบเก่าทั้งหมดจะรวมกันเป็นเมธอด load เดียวใน PagingSource ซึ่งจะช่วยลดการทำโค้ดซ้ำ เนื่องจากตรรกะส่วนใหญ่ในเมธอดการโหลดในการใช้งานคลาส API แบบเก่ามักจะเหมือนกัน

พารามิเตอร์เมธอดการโหลดทั้งหมดจะถูกแทนที่ใน Paging 3 ด้วยคลาส LoadParams แบบ Sealed ซึ่งรวมถึงคลาสย่อยสำหรับประเภทการโหลดแต่ละประเภท หากต้องการแยกความแตกต่างระหว่างประเภทการโหลดในเมธอด load ให้ตรวจสอบคลาสย่อยของ LoadParams ที่ส่งผ่านเข้ามา ได้แก่ LoadParams.Refresh, LoadParams.Prepend, หรือ LoadParams.Append

ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้งาน PagingSource ได้ที่ กำหนดแหล่งข้อมูล

คีย์รีเฟรช

การใช้งาน PagingSource ต้องกำหนดวิธีที่การรีเฟรชจะกลับมาทำงานต่อจากกลางข้อมูลแบบแบ่งหน้าเว็บที่โหลดไว้ โดยทำได้ด้วยการใช้งาน getRefreshKey เพื่อแมปคีย์เริ่มต้นที่ถูกต้องโดยใช้ state.anchorPosition เป็นดัชนีที่เข้าถึงล่าสุด

// Replaces ItemKeyedDataSource.
override fun getRefreshKey(state: PagingState<String, User>): String? {
  return state.anchorPosition?.let { anchorPosition ->
    state.getClosestItemToPosition(anchorPosition)?.id
  }
}

// Replacing PositionalDataSource.
override fun getRefreshKey(state: PagingState<Int, User>): Int? {
  return state.anchorPosition
}

การแปลงรายการ

ในไลบรารี Paging เวอร์ชันที่ต่ำกว่า การแปลงข้อมูลแบบแบ่งหน้าเว็บจะขึ้นอยู่กับเมธอดต่อไปนี้

  • DataSource.map
  • DataSource.mapByPage
  • DataSource.Factory.map
  • DataSource.Factory.mapByPage

ใน Paging 3 การแปลงทั้งหมดจะใช้เป็นโอเปอเรเตอร์กับ PagingData หากคุณใช้เมธอดใดเมธอดหนึ่งในรายการก่อนหน้าเพื่อแปลงรายการแบบแบ่งหน้าเว็บ คุณต้องย้ายตรรกะการแปลงจาก DataSource ไปยัง PagingData เมื่อสร้าง Pager โดยใช้ PagingSource ใหม่

ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้การแปลงกับข้อมูลแบบแบ่งหน้าเว็บโดยใช้ Paging 3 ได้ที่ แปลงสตรีมข้อมูล

PagedList

ส่วนนี้อธิบายการเปลี่ยนแปลงที่จำเป็นทั้งหมดเพื่อย้ายข้อมูลการใช้งาน Paging แบบเก่าให้ใช้ Pager และ PagingData ใน Paging 3

คลาส PagedListBuilder

PagingData จะแทนที่ PagedList ที่มีอยู่จาก Paging 2 หากต้องการย้ายข้อมูลไปยัง PagingData คุณต้องอัปเดตข้อมูลต่อไปนี้

  • การกำหนดค่า Paging ย้ายจาก PagedList.Config ไปเป็น PagingConfig
  • คลาส Builder แบบเก่าจะรวมกันเป็นคลาส Pager เดียว
  • Pager แสดง Flow<PagingData> ที่สังเกตได้ด้วยพร็อพเพอร์ตี้ .flow
val flow = Pager(
  // Configure how data is loaded by passing additional properties to
  // PagingConfig, such as prefetchDistance.
  PagingConfig(pageSize = 20)
) {
  ExamplePagingSource(backend, query)
}.flow
  .cachedIn(viewModelScope)

ดูข้อมูลเพิ่มเติมเกี่ยวกับการตั้งค่าสตรีมแบบ Reactive ของออบเจ็กต์ PagingData โดยใช้ Paging 3 ได้ที่ตั้งค่าสตรีม PagingData

BoundaryCallback สำหรับแหล่งที่มาแบบเลเยอร์

ใน เพจจิ้ง 3 RemoteMediator จะแทนที่ PagedList.BoundaryCallback เป็นa ตัวจัดการสำหรับการแบ่งหน้าเว็บจากเครือข่ายและฐานข้อมูล

ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ RemoteMediator เพื่อแบ่งหน้าเว็บจากเครือข่ายและฐานข้อมูลใน Paging 3 ได้ที่ Codelab การแบ่งหน้าเว็บของ Android

LazyPagingItems

ส่วนนี้อธิบายการเปลี่ยนแปลงที่จำเป็นทั้งหมดเพื่อย้ายข้อมูลการใช้งาน Paging แบบเก่าให้ใช้ LazyPagingItems จาก Paging 3

Paging 3 มี collectAsLazyPagingItems เพื่อจัดการโฟลว์ PagingData ใหม่ หากต้องการย้ายข้อมูลเลเยอร์การนำเสนอ ให้ใช้ Artifact paging-compose และ collectAsLazyPagingItems เพื่อรวบรวมรายการ PagingData และแสดงรายการเหล่านั้นในฟังก์ชัน @Composable

ดูข้อมูลเพิ่มเติมเกี่ยวกับ LazyPagingItems ได้ที่ โหลดและแสดงข้อมูลแบบแบ่งหน้าเว็บ

การเปรียบเทียบและการอัปเดตรายการ

หากปัจจุบันคุณใช้ตรรกะการเปรียบเทียบรายการที่กำหนดเอง ให้ย้ายข้อมูลการใช้งานเพื่อใช้ LazyPagingItems ที่มีให้ใน Paging 3 แทน ระบุคีย์รายการในรายการแบบ Lazy เพื่อให้การเปรียบเทียบเกิดขึ้นอย่างถูกต้อง

@Composable
fun UserScreen(viewModel: UserViewModel) {
    // Collects the Flow into a LazyPagingItems object
    val lazyPagingItems = viewModel.pager.flow.collectAsLazyPagingItems()

    UserList(lazyPagingItems)
}

@Composable
fun UserScreen(viewModel: UserViewModel) {
    val lazyPagingItems = viewModel.pager.flow.collectAsLazyPagingItems()

    UserList(lazyPagingItems)
}

@Composable
fun UserList(lazyPagingItems: LazyPagingItems<User>) {
    LazyColumn {
        items(
            count = lazyPagingItems.itemCount,
            // Provide a stable key for each item, similar to DiffUtil in Views
            key = lazyPagingItems.itemKey { user -> user.id } 
        ) { index ->
            val user = lazyPagingItems[index]
            if (user != null) {
                UserRow(user = user)
            }
        }
    }
}

ดูข้อมูลเพิ่มเติมเกี่ยวกับคีย์รายการได้ที่ คีย์รายการ

สถานะการโหลด

ใน Paging 3 คุณไม่จำเป็นต้องใช้อะแดปเตอร์แยกต่างหากเพื่อแสดงส่วนหัวหรือส่วนท้ายสำหรับสถานะการโหลด ออบเจ็กต์ LazyPagingItems แสดงพร็อพเพอร์ตี้ loadState ที่คุณตรวจสอบได้โดยตรงภายใน LazyColumn

LazyColumn {
    // ... items(lazyPagingItems) go here ...

    // Show loading spinner at bottom of list when appending data
    if (lazyPagingItems.loadState.append is LoadState.Loading) {
        item {
            CircularProgressIndicator(modifier = Modifier.fillMaxWidth())
        }
    }
}

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับไลบรารี Paging ได้จากแหล่งข้อมูลเพิ่มเติมต่อไปนี้

เอกสารประกอบ

ดูเนื้อหา