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

RecyclerView加载更多失效:无ProgressBar/数据,Logcat警告修复求助

修复RecyclerView滚动加载时ProgressBar不显示且无数据加载的问题

这个问题的根源就是Logcat里的警告明确提示的——你在RecyclerView的滚动回调(比如OnScrollListener的onScrolled方法)里直接执行了修改Adapter数据的操作,而滚动回调可能在RecyclerView的measure/layout阶段运行,这时候修改数据会触发框架的限制,导致你的加载逻辑没正常执行,ProgressBar也无法显示。

核心修复步骤

1. 把所有数据修改操作延迟到主线程下一个消息帧

你当前的loadMore()方法开头就直接修改列表并通知Adapter更新,这部分是在滚动回调的同步流程里执行的,正是触发警告的原因。要把整个数据修改逻辑都放到Handler.post()或者View.post()里,避开measure/layout阶段。

修改后的loadMore()代码:

private void loadMore() {
    // 先判断是否正在加载,避免重复触发
    if (isLoading) return;
    isLoading = true;

    // 把所有操作放到主线程下一个消息帧执行,避开滚动回调的布局阶段
    new Handler(Looper.getMainLooper()).post(() -> {
        // 添加加载占位项(null),显示ProgressBar
        arraylist.add(null);
        mListadapter.notifyItemInserted(arraylist.size() - 1);

        // 模拟加载延迟(实际场景替换成网络请求/本地数据加载)
        new Handler(Looper.getMainLooper()).postDelayed(() -> {
            // 移除占位项
            arraylist.remove(arraylist.size() - 1);
            int scrollPosition = arraylist.size();
            mListadapter.notifyItemRemoved(scrollPosition);

            int currentSize = scrollPosition;
            int nextLimit = currentSize + 5;
            Log.e("currentSize", "" + currentSize);
            Log.e("nextLimit", "" + nextLimit);

            // 加载新数据(修复索引越界问题)
            int endIndex = Math.min(nextLimit, DataNoteImformation.id.length);
            while (currentSize < endIndex) {
                DataNote wp2 = new DataNote(
                        DataNoteImformation.id[currentSize],
                        DataNoteImformation.branchArray[currentSize],
                        DataNoteImformation.assetcodeArray[currentSize],
                        DataNoteImformation.customerArray[currentSize],
                        DataNoteImformation.licenseplateArray[currentSize]
                );
                arraylist.add(wp2);
                currentSize++;
            }

            // 高效通知Adapter数据更新(比notifyDataSetChanged性能更好)
            mListadapter.notifyItemRangeInserted(scrollPosition, currentSize - scrollPosition);
            isLoading = false;
        }, 2000);
    });
}

2. 确保Adapter正确处理加载占位项

你的Adapter需要区分普通数据项和加载项的ViewType,这样才能正常显示ProgressBar:

// 在Adapter里定义两个ViewType常量
private static final int VIEW_TYPE_ITEM = 0;
private static final int VIEW_TYPE_LOADING = 1;

@Override
public int getItemViewType(int position) {
    // 判断当前项是否是加载占位项(null)
    return arraylist.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == VIEW_TYPE_ITEM) {
        // 创建普通数据项的ViewHolder(你的原有逻辑)
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.your_item_layout, parent, false);
        return new YourItemViewHolder(view);
    } else {
        // 创建加载项的ViewHolder(显示ProgressBar)
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_loading, parent, false);
        return new LoadingViewHolder(view);
    }
}

// 加载项的ViewHolder
static class LoadingViewHolder extends RecyclerView.ViewHolder {
    ProgressBar progressBar;
    public LoadingViewHolder(View itemView) {
        super(itemView);
        progressBar = itemView.findViewById(R.id.progress_bar);
    }
}

3. 修复滚动回调里的调用逻辑

如果你之前是在OnScrollListener的onScrolled里直接调用loadMore(),现在要确保调用时机正确,并且加上isLoading的判断:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);
        LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
        
        // 判断是否滚动到底部,且不在加载中
        if (!isLoading && layoutManager != null && layoutManager.findLastCompletelyVisibleItemPosition() == arraylist.size() - 1) {
            // 延迟调用loadMore,确保不在布局阶段执行
            recyclerView.post(() -> loadMore());
        }
    }
});

额外优化点

  • 替换notifyDataSetChanged()为notifyItemRangeInserted(),避免RecyclerView重新渲染所有项,提升性能
  • 修复了原代码中数组索引越界的问题(原currentSize + 1 <= nextLimit会导致访问到数组长度的索引,数组索引从0开始,改成currentSize < endIndex更安全)
  • 给Handler指定主线程的Looper,避免在非主线程创建Handler导致的异常

内容的提问来源于stack exchange,提问作者D3D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:24:19