JectPack组件Paging3问题汇总(见过的没见过的都在这里了)

最近在项目中,使用到了Paging3作为分页组件开发分页功能,在使用的过程中,还是碰到了很多问题,这里简单汇总一下,后续会出一期源码分析

1 添加Footer或者Header

在Paging3中,已经支持动态添加头部或者尾部,实现上拉加载和下拉刷新;经常在项目中碰到的一个场景就是,当分页数据加载完成后,需要显示一个已经加载完成的底部标签,那么就可以给列表添加一个尾部

在Paging3中使用RecyclerView加载分页数据,就得使用PagingDataAdapter作为适配器,该适配器有3个api用于添加头部或者尾部,其中添加尾部使用withLoadStateFooter

这里就有一个问题,在官网文档中也没有提及,其他博客中也写的非常笼统,

adapter = PagingListAdapter(requireContext())
val withLoadStateFooter = adapter.withLoadStateFooter(FootAdapter(requireContext()))
//这里返回的adapter为ConcatAdapter
binding.rvContent.adapter = withLoadStateFooter

调用withLoadStateFooter后返回的是ConcatAdapter,就是将列表主体和尾部结合的适配器,给RecyclerView设置适配器不能再设置之前的PagingListAdapter,而是需要设置这个ConcatAdapter,不然没有效果

2 LoadStateAdapter的使用

在Paging3中,提供了另一个状态适配器LoadStateAdapter,通过判断数据加载的状态,来控制UI的展示或者隐藏,来完成交互

class FootAdapter(
    val context: Context
) : LoadStateAdapter<FooterViewHolder>() {


    override fun onBindViewHolder(holder: FooterViewHolder, loadState: LoadState) {

        when(loadState){

            is LoadState.NotLoading -> {

                holder.binding.tvFinish.visibility = View.VISIBLE
            }
            is LoadState.Loading ->{

                holder.binding.tvFinish.visibility = View.GONE
            }
            else -> {

            }
        }


    }

    override fun onCreateViewHolder(parent: ViewGroup, loadState: LoadState): FooterViewHolder {

        return FooterViewHolder(
            LayoutPagingFootBinding.bind(
                LayoutInflater.from(context).inflate(R.layout.layout_paging_foot,parent,false)
            )
        )
    }

    /**
     * 重写该方法,否则底部LoadStatus不展示,闪过
     * By default, both [LoadState.Loading] and [LoadState.Error] are presented as adapter items,
     * other states are not. To configure this, override [displayLoadStateAsItem].
     */
    override fun displayLoadStateAsItem(loadState: LoadState): Boolean {

         return loadState is LoadState.Loading ||
                loadState is LoadState.Error ||
                (loadState is LoadState.NotLoading && loadState.endOfPaginationReached);
    }

    override fun getStateViewType(loadState: LoadState): Int {

        return LoadStatus.END.ordinal
    }
}

class FooterViewHolder(
    var binding: LayoutPagingFootBinding
) : RecyclerView.ViewHolder(binding.root)

问题1:Footer一闪而过,只有在加载的时候显示,加载完成之后,就不显示了

在LoadStateAdapter中有一个方法,displayLoadStateAsItem,官方的注释中写道

默认情况下,[LoadState.Loading] 和 [LoadState.Error] 都显示为适配器项,其他的状态不显示,如果想要其他的状态显示,那么就重写这个方法

所以,当列表加载完成之后,尾部不显示的原因就在这里,所以需要重写,displayLoadStateAsItem,当列表加载到底部的时候,也需要展示为适配器的选项

问题2:如果RecyclerView设置了GridLayoutManager,如何让Footer独占一行?

binding.rvContent.layoutManager =
            GridLayoutManager(requireContext(), 3, GridLayoutManager.VERTICAL, false)
                .apply {

                spanSizeLookup = object : GridLayoutManager.SpanSizeLookup(){
                    override fun getSpanSize(position: Int): Int {

                       return if(withLoadStateFooter.getItemViewType(position) == LoadStatus.END.ordinal) spanCount else 1
                    }
                }
            }

默认情况下,如果GridLayoutManager设置了列数超过1,那么显示的Footer也只是占据1个item的位置,这种情况下就不符合设计的需求,要求当显示Foot的时候,需要独占一行。

这个时候,需要设置GridLayoutManager的spanSizeLookup属性,判断当列表到尾部的时候,将spanSizeLookup设置为一行(也就是列数)

如何判断是否到了底部,就需要通过ConcatAdapter判断item的类型,在LoadStateAdapter中重写getStateViewType, 因为是Foot,所以就是一种类型直接返回,ConcatAdapter在判断类型时,如果是Foot,就设置spanSizeLookup为spanCount

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Awesome_lay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值