• Compose - 使用 Paging


    一、添加依赖

    查看官方最新版本

    1. val paging_version = "3.2.1"
    2. implementation("androidx.paging:paging-runtime:$paging_version")
    3. implementation("androidx.paging:paging-compose:$paging_version")

    二、定义数据源 PagingSource

    是对其它数据源的封装,因此和 Repository 定义在同一个 .kt 文件中并私有化。自定义一个类继承 PagingSource 并重写 load() 来提供获取页面数据。

    1. class DemoRepository {
    2. fun getData() = Pager(PagingConfig(10)) {
    3. PagingResource()
    4. }.flow
    5. }
    6. private class PagingResource : PagingSource<Int, HotNewestArticleBean.HotNewestArticle.Article>() {
    7. private val startPage = 0
    8. override suspend fun load(params: LoadParams<Int>): LoadResult<Int, HotNewestArticleBean.HotNewestArticle.Article> {
    9. return try {
    10. val currentPage = params.key ?: startPage
    11. val data = getData(currentPage)
    12. val prevKey = if (currentPage > startPage) currentPage - 1 else null
    13. val nextKey = if (data.isNotEmpty()) currentPage + 1 else null
    14. LoadResult.Page(data, prevKey, nextKey)
    15. } catch (e: Exception) {
    16. LoadResult.Error(e)
    17. }
    18. }
    19. override fun getRefreshKey(state: PagingState<Int, HotNewestArticleBean.HotNewestArticle.Article>): Int? {
    20. return null
    21. }
    22. //具体获取数据的方法。这里能更细分的对异常处理,否则在load()中合并返回后在UI中难区分。
    23. //但处理后还是要抛出异常,不然load()不会返回异常,影响UI中对Paging状态判断
    24. private suspend fun getData(currentPage: Int): List {
    25. var data: List = emptyList()
    26. runCatching {
    27. withContext(Dispatchers.IO) {
    28. RetrofitClient.apiService.newestArticle(currentPage.toString())
    29. }
    30. }.onSuccess { response ->
    31. response.getData().onSuccess {
    32. data = it.datas
    33. }.onFailure {
    34. Log.e("服务器错误", it.message.toString())
    35. throw Exception("服务器错误:${it.message}")
    36. }
    37. }.onFailure {
    38. Log.e("本地错误", it.message.toString())
    39. throw Exception("本地错误:${it.message}")
    40. }
    41. return data
    42. }
    43. }

    三、ViewModel 中调用

    1. class DemoViewModel : ViewModel() {
    2. private val repository = DemoRepository()
    3. var pagingDataFlow = repository.getData().cachedIn(viewModelScope) //缓存在ViewModel中
    4. }

    四、UI

    1. @Composable
    2. fun DemoScreen(
    3. viewModel: DemoViewModel = viewModel()
    4. ) {
    5. //将Paging的数据从Flow转为可供LazyColumn使用的
    6. val lazyPagingItems = viewModel.pagingDataFlow.collectAsLazyPagingItems()
    7. //监听Paging状态
    8. when (lazyPagingItems.loadState.refresh) {
    9. //正在加载
    10. is LoadState.Loading -> {}
    11. //加载错误(这里的错误是PagingSource里捕获的)
    12. is LoadState.Error -> {}
    13. //当没有加载动作并且没有错误的时候
    14. is LoadState.NotLoading -> {}
    15. }
    16. LazyColumn(
    17. modifier = Modifier.fillMaxSize(),
    18. state = lazyListState
    19. ){
    20. items(
    21. count = lazyPagingItems.itemCount,
    22. key = lazyPagingItems.itemKey { it.id }
    23. ) { index ->
    24. val bean = lazyPagingItems[index]
    25. if (bean != null) {
    26. val author = bean.author
    27. val shareUser = bean.shareUser
    28. val superChapterName = bean.superChapterName
    29. Item(
    30. title = bean.title,
    31. author = if (author.isEmpty()) String.format("%s · %s", superChapterName, shareUser) else String.format("%s · %s", superChapterName, author),
    32. time = bean.niceDate,
    33. )
    34. } else {
    35. Text("")
    36. }
    37. }
    38. }
    39. }

  • 相关阅读:
    STM32单片机驱动L298N
    公众号开发教程:微信视频预览一半就要收费是怎么做的
    用echarts实现柱状图
    猿创征文 | Spring框架【管理对象(IOC详解)】
    mysql-1:认识mysql
    如何让游戏中的随机因素重新赢得玩家信任
    监控GreenPlum表的增量代码怎么写比较合适
    线性代数应用基础补充2
    spicy(二)unit hooks
    【设计模式】八、桥接模式
  • 原文地址:https://blog.csdn.net/HugMua/article/details/134271625