You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无限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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:08:58