无限RecyclerView分页中出现多个ProgressBar的问题
解决RecyclerView分页加载时多个ProgressBar和页码持续递增的问题
嘿,我来帮你搞定这个分页加载的bug!你遇到的多个ProgressBar冒出来、页码一直乱涨的情况,基本都是没做好请求状态控制和分页逻辑的边界处理,这也是很多人做分页时容易踩的坑,咱们一步步来修复:
核心问题分析
之所以会出现这种情况,主要是因为:
- 没有标记「正在加载中」的状态,用户滚动时会多次触发加载请求,导致多个ProgressBar被添加
- 页码递增时机不对,不管请求成功失败都涨页码,或者没判断是否还有更多数据就一直涨
具体解决方案
1. 增加「加载中」状态锁,防止并发请求
在你的Fragment里加几个关键变量,用来控制加载状态和分页逻辑:
// Fragment内的成员变量 private var isLoading = false // 标记是否正在发起请求 private var hasMore = true // 标记是否还有更多数据可加载 private var currentPage = 1 // 当前请求的页码
然后在加载更多的方法里,先做状态校验,避免重复请求:
private fun loadMoreBlogs() { // 正在加载/没有更多数据时,直接返回,不触发新请求 if (isLoading || !hasMore) return isLoading = true // 给列表末尾添加ProgressBar(假设你用了多类型Item,LoadingItem是加载占位实体) blogList.add(LoadingItem()) yourBlogAdapter.notifyItemInserted(blogList.size - 1) // 发起API请求 yourBlogViewModel.getBlogs(page = currentPage).observe(viewLifecycleOwner) { result -> // 请求结束后先移除ProgressBar,不管成功还是失败 blogList.removeLast() yourBlogAdapter.notifyItemRemoved(blogList.size) when(result) { is ApiResponse.Success -> { val newBlogs = result.data if (newBlogs.isEmpty()) { // 没有更多数据了,关闭加载开关 hasMore = false } else { // 将新数据添加到列表 blogList.addAll(newBlogs) yourBlogAdapter.notifyItemRangeInserted( blogList.size - newBlogs.size, newBlogs.size ) // 只有请求成功且拿到新数据,才递增页码 currentPage += 1 } } is ApiResponse.Error -> { // 处理错误,比如给用户弹个提示 Toast.makeText(requireContext(), "加载失败,请稍后重试", Toast.LENGTH_SHORT).show() } } // 请求彻底结束,解锁加载状态 isLoading = false } }
2. 修正ScrollListener的触发条件
很多时候ScrollListener的判断逻辑太宽松,导致频繁触发加载。调整一下判断条件,只在符合所有要求时才触发加载:
yourRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { super.onScrolled(recyclerView, dx, dy) val layoutManager = recyclerView.layoutManager as LinearLayoutManager val lastVisibleItemPos = layoutManager.findLastVisibleItemPosition() val totalItemCount = layoutManager.itemCount // 严格判断触发加载的条件:向下滚动+不在加载中+还有更多数据+最后一个可见item是列表末尾 if (dy > 0 && !isLoading && hasMore && lastVisibleItemPos == totalItemCount - 1) { loadMoreBlogs() } } })
3. 统一ProgressBar的增删逻辑
不要在多个地方添加ProgressBar,只在loadMoreBlogs方法开头添加,请求结束后立刻移除(不管成功失败),这样就不会出现多个ProgressBar堆积的情况。同时要确保你的Adapter能正确区分普通博客项和加载项:
// 在你的BlogAdapter中 private const val VIEW_TYPE_BLOG = 0 private const val VIEW_TYPE_LOADING = 1 override fun getItemViewType(position: Int): Int { return if (blogList[position] is LoadingItem) { VIEW_TYPE_LOADING } else { VIEW_TYPE_BLOG } }
4. 严格控制页码递增时机
只有当API请求成功,并且确实返回了新数据的时候,才去递增currentPage。如果请求失败或者返回空数据,绝对不要动页码——不然下次请求会直接跳页,导致拿不到正确的数据,进而反复触发加载逻辑。
总结
只要做好「加载状态锁」「是否还有更多数据的标记」「页码递增的时机控制」,就能彻底解决多个ProgressBar和页码乱跳的问题啦!
内容的提问来源于stack exchange,提问作者Yesha
相关产品推荐
相关产品推荐

