Android开发 Recyclerview 实现预加载

目录

 一、问题

二,出发点滑动监听OnScrollListener

三、预加载时机的判断

四、适配LayoutManager

1、检查使用的LayoutManager

2、针对LayoutManager 进行处理 

3、预加载的回调接口 

五、存在的BUG


一、问题

在通过其他三方刷新库进行对列表数据进行加载时,总是需要在滑动底部无数据时触发一个加载动画在触发加载回调函数进行数据请求加载,但是这个延迟给我的感觉不是很流畅,有点打断用户的列表滑动预览的操作,所以思考有没有一种可以让用户一直下滑加载数据直到没有数据可以提供为止而不是在一页数据到底后触发一个加载动画打断用户的滑动。

效果就是可以让用户一直滑动加载数据而不打断这个滑动行为,实现数据加载的过程用户不需要感知这个过程。

二,出发点滑动监听OnScrollListener

也就是在一页数据未显示数量的达到一个阈值,触发一个预加载的回调,去加载数据并进行填充列表,尽量不打断用户的下滑操作。

class PreloadScrollListener(private val listener: OnPreloadListener) : RecyclerView.OnScrollListener() {

    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        if (dy < 0) return  //排除 向上滑动
       
    }

   

}

 因为是下滑的预加载所以 前进行 滑动方向的判断;

dy:, dy > 0  向下滚动  ;dy< 0 向上 滚动;

第一 步滑动方向上面代码已经实现。

三、预加载时机的判断

第二步 什么时候该预加载了,跟着代码我说一下我的思路(使用的是LinearLayoutManager演示):

1、没有数据时 肯定就不需要触发预加载了 排除;

    private var currentTotal = 0
    private fun linearLayoutPreload(layoutManager: LinearLayoutManager) {
        val totalSize = layoutManager.itemCount
        if (totalSize == 0) return
       
    }

2、当分页加载数量刚好一页 也没有必要预加载了 肯定会打断滑动 排除;

private var currentTotal = 0
    private fun linearLayoutPreload(layoutManager: LinearLayoutManager) {
        val totalSize = layoutManager.itemCount
        if (totalSize == 0) return
        val firstIndex = layoutManager.findFirstVisibleItemPosition()
        val lastIndex = layoutManager.findLastVisibleItemPosition()
        val pageSize = lastIndex - firstIndex
        if (pageSize == totalSize) return
      
    }

3、当未显示的item 数量 大于我们设置的阈值 也排除;

private var currentTotal = 0
    private fun linearLayoutPreload(layoutManager: LinearLayoutManager) {
        val totalSize = layoutManager.itemCount
        if (totalSize == 0) return
        val firstIndex = layoutManager.findFirstVisibleItemPosition()
        val lastIndex = layoutManager.findLastVisibleItemPosition()
        val pageSize = lastIndex - firstIndex
        if (pageSize == totalSize) return
        val hideSize = totalSize - lastIndex
        if (hideSize > thresholdSize) return //排除不需要预加载
       
    }

4、但是 我们的阈值通常大于1 ,所以会造成 多次触发预加载 ,那当数据总数 不变说明预加载还没加载到数据 。

private var currentTotal = 0
    private fun linearLayoutPreload(layoutManager: LinearLayoutManager) {
        val totalSize = layoutManager.itemCount
        if (totalSize == 0) return
        val firstIndex = layoutManager.findFirstVisibleItemPosition()
        val lastIndex = layoutManager.findLastVisibleItemPosition()
        val pageSize = lastIndex - firstIndex
        if (pageSize == totalSize) return
        val hideSize = totalSize - lastIndex
        if (hideSize > thresholdSize) return //排除不需要预加载
        if (currentTotal == totalSize) return  //排除重复滑动触发
        this.currentTotal = totalSize
        //可以正常触发预加载了
    }

四、适配LayoutManager

1、检查使用的LayoutManager

class PreloadScrollListener(private val listener: OnPreloadListener) : RecyclerView.OnScrollListener() {

    companion object {
        var thresholdSize = 5   //触发预加载的未加载的Item数量
    }

    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        if (dy < 0) return  //排除 向上滑动
        when (val layoutManager = recyclerView.layoutManager) {
            is LinearLayoutManager -> {
                linearLayoutPreload(layoutManager)
            }
            is GridLayoutManager -> {
                gridLayoutPreload(layoutManager)
            }
        }
    }

   

}

 thresholdSize  这个是触发预加载的阈值 ,可以使用 PreloadScrollListener.thresholdSize 进行 动态修改。

2、针对LayoutManager 进行处理 

 private var currentTotal = 0

    private fun gridLayoutPreload(layoutManager: GridLayoutManager) {
        val totalSize = layoutManager.itemCount
        if (totalSize == 0) return
        val firstIndex = layoutManager.findFirstVisibleItemPosition()
        val lastIndex = layoutManager.findLastVisibleItemPosition()
        val pageSize = lastIndex - firstIndex
        if (pageSize == totalSize) return
        val hideSize = totalSize - lastIndex
        if (hideSize > thresholdSize) return //排除不需要预加载
        if (currentTotal == totalSize) return  //排除重复滑动触发
        this.currentTotal = totalSize
        listener.onPreLoad(pageSize + 1)
    }

    private fun linearLayoutPreload(layoutManager: LinearLayoutManager) {
        val totalSize = layoutManager.itemCount
        if (totalSize == 0) return
        val firstIndex = layoutManager.findFirstVisibleItemPosition()
        val lastIndex = layoutManager.findLastVisibleItemPosition()
        val pageSize = lastIndex - firstIndex
        if (pageSize == totalSize) return
        val hideSize = totalSize - lastIndex
        if (hideSize > thresholdSize) return //排除不需要预加载
        if (currentTotal == totalSize) return  //排除重复滑动触发
        this.currentTotal = totalSize
        listener.onPreLoad(pageSize + 1)
    }

3、预加载的回调接口 

interface OnPreloadListener {

    fun onPreLoad(pageSize: Int)

}

pageSize :是一个当前recycleView显示的Item最大数量。

五、存在的BUG

1、当分页加载时当加载的数据总数刚好处于阈值内会再次触发预加载回调!

2、适配的LayoutManager 比较少!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值