如何修改分页扩展方法适配多Fragment及不同ViewModel并修复运行异常
优化后的通用分页滚动监听方案
原代码核心问题
- 强转
LinearLayoutManager,如果RecyclerView使用其他布局管理器会直接崩溃 - 没有加载状态锁,滑动到底部会连续触发多次接口请求,导致请求错乱、列表跳动
- 硬编码绑定
EverythingViewModel,无法复用到其他业务场景 - 没有无更多数据的判断,即使后端已经返回完所有数据仍会重复发起无用请求
通用封装实现(Kotlin)
/** * 通用RecyclerView分页滚动监听 * @param visibleThreshold 触发预加载的剩余可见item数量,默认提前1个item开始加载 * @param isLoading 当前是否正在加载数据,由外部ViewModel维护状态 * @param hasMoreData 是否还有更多数据可加载,由外部ViewModel维护状态 * @param onLoadMore 触发分页时的回调,执行具体的分页请求逻辑 */ fun RecyclerView.addPaginationScrollListener( visibleThreshold: Int = 1, isLoading: () -> Boolean, hasMoreData: () -> Boolean, onLoadMore: () -> Unit ): RecyclerView.OnScrollListener { val scrollListener = object : RecyclerView.OnScrollListener() { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { super.onScrolled(recyclerView, dx, dy) // 只有向上滑动、不在加载中、还有更多数据时才判断分页条件 if (dy <= 0 || isLoading() || !hasMoreData()) return val layoutManager = recyclerView.layoutManager as? LinearLayoutManager ?: return val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition() val visibleItemCount = layoutManager.childCount val totalItemCount = layoutManager.itemCount // 满足分页触发条件 if (visibleItemCount + firstVisibleItemPosition + visibleThreshold >= totalItemCount) { onLoadMore() } } } this.addOnScrollListener(scrollListener) return scrollListener }
ViewModel适配要求
所有需要使用分页的ViewModel无需继承统一父类,只需要维护三个核心属性、一个请求方法即可:
page: Int当前页码,分页请求时传入接口isLoading: Boolean加载状态锁,请求开始时设为true,请求结束(成功/失败)都设为falsehasMoreData: Boolean是否还有更多数据,接口返回列表为空/达到总页数时设为false- 对应业务的分页请求方法(比如
getEverything()、getTopNews()等)
多场景使用示例
原有Everything业务调用
everythingRecycler.addPaginationScrollListener( isLoading = { viewModel.isLoading }, hasMoreData = { viewModel.hasMoreData }, onLoadMore = { viewModel.page++ viewModel.getEverything() } )
其他业务ViewModel调用(第二个Fragment示例)
topNewsRecycler.addPaginationScrollListener( visibleThreshold = 2, // 可自定义提前2个item预加载,提升体验 isLoading = { topNewsViewModel.isLoading }, hasMoreData = { topNewsViewModel.hasMoreData }, onLoadMore = { topNewsViewModel.page++ topNewsViewModel.getTopNews() } )
稳定性优化说明
- 新增
isLoading状态锁,避免同一时间发起多个分页请求 - 新增
hasMoreData判断,无更多数据时不再触发无用请求 - 布局管理器用安全强转
as?,非LinearLayoutManager场景不会崩溃 - 支持自定义预加载阈值,提前发起请求用户无感知,滑动更流畅
内容的提问来源于stack exchange,提问作者Radin
相关产品推荐
相关产品推荐

