目录
一、问题
在通过其他三方刷新库进行对列表数据进行加载时,总是需要在滑动底部无数据时触发一个加载动画在触发加载回调函数进行数据请求加载,但是这个延迟给我的感觉不是很流畅,有点打断用户的列表滑动预览的操作,所以思考有没有一种可以让用户一直下滑加载数据直到没有数据可以提供为止而不是在一页数据到底后触发一个加载动画打断用户的滑动。
效果就是可以让用户一直滑动加载数据而不打断这个滑动行为,实现数据加载的过程用户不需要感知这个过程。
二,出发点滑动监听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 比较少!