Jetpack Compose 讲解如何利用Paging3实现分页加载

3,858 阅读2分钟

「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战

添加依赖库

implementation "androidx.paging:paging-runtime:3.0.0-beta02"
implementation "androidx.paging:paging-compose:1.0.0-alpha08"

第一步PagingSource

PagingSource:用于从某些源抽象可分页静态数据的基类,其中加载数据页通常是一项昂贵的操作。公共分页资源的一些示例可能来自网络或数据库 PagingSource实例用于为PagingData实例加载数据页。

PagingSource有两个参数
key:要将PagingSource加载的数据呈现给LazyColumn,
Value:分页源加载的数据类型

可以通过传递Int页码给 Retrofit,从网络加载Value对象

创建一个Pager实例,它提供一个PagingData流

 PagingSource<Int, String>()

这里我用String演示

PagingSourceAPI类包括 load() 方法,要重写这个方法,在里面实现从相应的数据源中请求分页数据逻辑。

load(params: LoadParams<Int>): LoadResult<Int, String> {
    return try {
        val nextPage = params.key ?: 1
        val datas = mutableListOf(
           ...模拟的假数据
        )
        LoadResult.Page(...)
    } catch (e: Exception) {
        ...加载错误
    }
}

LoadResult.Page()要传入三个参数

data = 模拟的假数据,
prevKey = 如果可以继续加载更多数据,则为上一页的键,否则为null。
nextKey = 如果可以继续加载更多数据,则为下一页的键,否则为null。

如果加载出问题就返回 LoadResult.Error(e)

---------------------------完整代码 start-----------------------------

class SimpleSource : PagingSource<Int, String>() {
    override fun getRefreshKey(state: PagingState<Int, String>): Int? =null

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, String> {
        return try {
            val nextPage = params.key ?: 1
            val datas = mutableListOf(
                "hello",
                "hi",
                "你好呀",
                "点个赞叭!",
                "关注我,下篇详细教你封装下拉刷新上拉加载"
            )
            LoadResult.Page(
                data = datas,
                prevKey = if (nextPage == 1) null else nextPage - 1,
                nextKey = if (nextPage < 100) nextPage + 1 else null
            )
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }
}

ViewModel

Pager来构造PagingData对象和 PagingConfig配置

val projects = Pager(PagingConfig(pageSize = 3)){
    SimpleSource()
}.flow.cachedIn(viewModelScope)

渲染页面

@Composable
fun pagingDemo(viewModel: MyNoticeViewModel) {
    val datas = viewModel.projects.collectAsLazyPagingItems()
    LazyColumn(content = {
        itemsIndexed(datas) { _, data ->
            Box(
                Modifier
                    .padding(horizontal = 14.dp, vertical = 4.dp)
                    .fillMaxWidth()
                    .height(60.dp)
                    .border(1.dp, Color.Red, RoundedCornerShape(5.dp))
                    .padding(start = 10.dp),
                contentAlignment = Alignment.CenterStart
            ) {
                Text(text = data ?: "")
            }
        }
    })
}

onCreate下调用

setContent {
pagingDemo(viewModel)

}

---------------------------完整代码 end-----------------------------

collectAsLazyPagingItems的作用是:从该PagingData流收集值,并在LazyPagingItems实例中表示这些值。LazyListScope中的items和itemsIndexed方法可以使用LazyPagingItems实例来显示从PagingData流中获得的数据。

用LazyColumn来演示效果
为了美观我加个黑色边框修饰一下

border(1.dp, Color.Red, RoundedCornerShape(5.dp)

效果图 c569c952d8abde8e858208461ad330f.jpg

下篇Paging3+retrofit2实战