Compose
一、添加依赖
查看官方最新版本
val paging_version = "3.2.1"
implementation("androidx.paging:paging-runtime:$paging_version")
implementation("androidx.paging:paging-compose:$paging_version")
二、定义数据源 PagingSource
是对其它数据源的封装,因此和 Repository 定义在同一个 .kt 文件中并私有化。自定义一个类继承 PagingSource 并重写 load() 来提供获取页面数据。
class DemoRepository {fun getData() = Pager(PagingConfig(10)) {PagingResource()}.flow
}private class PagingResource : PagingSource<Int, HotNewestArticleBean.HotNewestArticle.Article>() {private val startPage = 0override suspend fun load(params: LoadParams<Int>): LoadResult<Int, HotNewestArticleBean.HotNewestArticle.Article> {return try {val currentPage = params.key ?: startPageval data = getData(currentPage)val prevKey = if (currentPage > startPage) currentPage - 1 else nullval nextKey = if (data.isNotEmpty()) currentPage + 1 else nullLoadResult.Page(data, prevKey, nextKey)} catch (e: Exception) {LoadResult.Error(e)}}override fun getRefreshKey(state: PagingState<Int, HotNewestArticleBean.HotNewestArticle.Article>): Int? {return null}//具体获取数据的方法。这里能更细分的对异常处理,否则在load()中合并返回后在UI中难区分。//但处理后还是要抛出异常,不然load()不会返回异常,影响UI中对Paging状态判断private suspend fun getData(currentPage: Int): List<HotNewestArticleBean.HotNewestArticle.Article> {var data: List<HotNewestArticleBean.HotNewestArticle.Article> = emptyList()runCatching {withContext(Dispatchers.IO) {RetrofitClient.apiService.newestArticle(currentPage.toString())}}.onSuccess { response ->response.getData().onSuccess {data = it.datas}.onFailure {Log.e("服务器错误", it.message.toString())throw Exception("服务器错误:${it.message}")}}.onFailure {Log.e("本地错误", it.message.toString())throw Exception("本地错误:${it.message}")}return data}
}
三、ViewModel 中调用
class DemoViewModel : ViewModel() {private val repository = DemoRepository()var pagingDataFlow = repository.getData().cachedIn(viewModelScope) //缓存在ViewModel中
}
四、UI
@Composable
fun DemoScreen(viewModel: DemoViewModel = viewModel()
) {//将Paging的数据从Flow转为可供LazyColumn使用的val lazyPagingItems = viewModel.pagingDataFlow.collectAsLazyPagingItems()//监听Paging状态when (lazyPagingItems.loadState.refresh) {//正在加载is LoadState.Loading -> {}//加载错误(这里的错误是PagingSource里捕获的)is LoadState.Error -> {}//当没有加载动作并且没有错误的时候is LoadState.NotLoading -> {}}LazyColumn(modifier = Modifier.fillMaxSize(),state = lazyListState){items(count = lazyPagingItems.itemCount,key = lazyPagingItems.itemKey { it.id }) { index ->val bean = lazyPagingItems[index]if (bean != null) {val author = bean.authorval shareUser = bean.shareUserval superChapterName = bean.superChapterNameItem(title = bean.title,author = if (author.isEmpty()) String.format("%s · %s", superChapterName, shareUser) else String.format("%s · %s", superChapterName, author),time = bean.niceDate,)} else {Text("")}}}
}
Compose
一、添加依赖
查看官方最新版本
val paging_version = "3.2.1"
implementation("androidx.paging:paging-runtime:$paging_version")
implementation("androidx.paging:paging-compose:$paging_version")
二、定义数据源 PagingSource
是对其它数据源的封装,因此和 Repository 定义在同一个 .kt 文件中并私有化。自定义一个类继承 PagingSource 并重写 load() 来提供获取页面数据。
class DemoRepository {fun getData() = Pager(PagingConfig(10)) {PagingResource()}.flow
}private class PagingResource : PagingSource<Int, HotNewestArticleBean.HotNewestArticle.Article>() {private val startPage = 0override suspend fun load(params: LoadParams<Int>): LoadResult<Int, HotNewestArticleBean.HotNewestArticle.Article> {return try {val currentPage = params.key ?: startPageval data = getData(currentPage)val prevKey = if (currentPage > startPage) currentPage - 1 else nullval nextKey = if (data.isNotEmpty()) currentPage + 1 else nullLoadResult.Page(data, prevKey, nextKey)} catch (e: Exception) {LoadResult.Error(e)}}override fun getRefreshKey(state: PagingState<Int, HotNewestArticleBean.HotNewestArticle.Article>): Int? {return null}//具体获取数据的方法。这里能更细分的对异常处理,否则在load()中合并返回后在UI中难区分。//但处理后还是要抛出异常,不然load()不会返回异常,影响UI中对Paging状态判断private suspend fun getData(currentPage: Int): List<HotNewestArticleBean.HotNewestArticle.Article> {var data: List<HotNewestArticleBean.HotNewestArticle.Article> = emptyList()runCatching {withContext(Dispatchers.IO) {RetrofitClient.apiService.newestArticle(currentPage.toString())}}.onSuccess { response ->response.getData().onSuccess {data = it.datas}.onFailure {Log.e("服务器错误", it.message.toString())throw Exception("服务器错误:${it.message}")}}.onFailure {Log.e("本地错误", it.message.toString())throw Exception("本地错误:${it.message}")}return data}
}
三、ViewModel 中调用
class DemoViewModel : ViewModel() {private val repository = DemoRepository()var pagingDataFlow = repository.getData().cachedIn(viewModelScope) //缓存在ViewModel中
}
四、UI
@Composable
fun DemoScreen(viewModel: DemoViewModel = viewModel()
) {//将Paging的数据从Flow转为可供LazyColumn使用的val lazyPagingItems = viewModel.pagingDataFlow.collectAsLazyPagingItems()//监听Paging状态when (lazyPagingItems.loadState.refresh) {//正在加载is LoadState.Loading -> {}//加载错误(这里的错误是PagingSource里捕获的)is LoadState.Error -> {}//当没有加载动作并且没有错误的时候is LoadState.NotLoading -> {}}LazyColumn(modifier = Modifier.fillMaxSize(),state = lazyListState){items(count = lazyPagingItems.itemCount,key = lazyPagingItems.itemKey { it.id }) { index ->val bean = lazyPagingItems[index]if (bean != null) {val author = bean.authorval shareUser = bean.shareUserval superChapterName = bean.superChapterNameItem(title = bean.title,author = if (author.isEmpty()) String.format("%s · %s", superChapterName, shareUser) else String.format("%s · %s", superChapterName, author),time = bean.niceDate,)} else {Text("")}}}
}