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

RecyclerView传onBindViewHolder的ArrayList大小给getItemCount

问题核心原因
  • 你在onBindViewHolder里创建的newStatusList、size都是方法局部变量,作用域仅限当前方法执行期间,getItemCount()根本访问不到这些值,自然返回无效结果。
  • 每次onBindViewHolder触发时你都重新读数据库创建新列表,Adapter本身没有持有持久的数据源引用,删除操作的改动根本不会留存,所以会出现删完条目又重新生成的问题。
  • onBindViewHolder的职责只是绑定指定位置的item数据,不适合做全量数据初始化、全量列表删改这类操作,频繁在这里查库还会导致滑动卡顿。
可行实现方案

核心思路是把列表数据源作为Adapter的全局成员变量维护,构造函数里只做一次初始数据加载,删除操作直接修改成员数据源、同步更新数据库后通知列表刷新即可,不需要在构造函数里访问position。
完整实现参考:

public class ChecklistAdapter extends RecyclerView.Adapter<ChecklistAdapter.VH> {
    // 声明为Adapter成员变量,所有内部方法都能访问
    private final ArrayList<String> statusList;
    private final DbHelper dbHelper;
    private final long currentChecklistId;

    // 构造函数只做初始化,不需要position参数
    public ChecklistAdapter(DbHelper dbHelper, long checklistId) {
        this.dbHelper = dbHelper;
        this.currentChecklistId = checklistId;
        // 初始化时只读一次数据库加载全量数据
        ChecklistHelper checklistHelper = dbHelper.getChecklists(checklistId);
        String rawStatus = checklistHelper.getStatus();
        String[] statusArr = rawStatus.split("\n");
        statusList = new ArrayList<>(Arrays.asList(statusArr));
    }

    @NonNull
    @Override
    public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // 正常写你的item布局加载逻辑
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_checklist, parent, false);
        return new VH(view);
    }

    @Override
    public void onBindViewHolder(@NonNull VH holder, int position) {
        // 只做当前position的数据绑定,不要在这里查全量库、重建列表
        String itemContent = statusList.get(position);
        holder.tvStatus.setText(itemContent);

        // 删除逻辑绑定到对应控件的点击事件上,点击时再拿当前位置
        holder.btnDelete.setOnClickListener(v -> {
            // 用getAdapterPosition拿实时位置,避免位置错乱
            int adapterPos = holder.getAdapterPosition();
            if (adapterPos == RecyclerView.NO_POSITION) return;

            // 1. 先删内存里的数据源
            statusList.remove(adapterPos);
            // 2. 同步更新数据库持久化
            StringBuilder newStatusBuilder = new StringBuilder();
            for (int i = 0; i < statusList.size(); i++) {
                newStatusBuilder.append(statusList.get(i));
                if (i != statusList.size() - 1) newStatusBuilder.append("\n");
            }
            ChecklistHelper updateBean = new ChecklistHelper();
            updateBean.setId(currentChecklistId);
            updateBean.setStatus(newStatusBuilder.toString());
            dbHelper.updateChecklist(updateBean); // 替换成你自己的数据库更新方法
            // 3. 通知UI刷新
            notifyItemRemoved(adapterPos);
            // 刷新后续item位置,避免角标错位
            notifyItemRangeChanged(adapterPos, statusList.size() - adapterPos);
        });
    }

    @Override
    public int getItemCount() {
        // 直接返回成员列表的长度,不需要单独维护size变量
        return statusList.size();
    }

    static class VH extends RecyclerView.ViewHolder {
        TextView tvStatus;
        ImageView btnDelete;
        public VH(@NonNull View itemView) {
            super(itemView);
            tvStatus = itemView.findViewById(R.id.tv_status);
            btnDelete = itemView.findViewById(R.id.btn_delete);
        }
    }
}
注意事项
  • 不要单独维护一个独立的size变量,直接调用数据源的size()方法返回即可,避免出现数据源修改了但size值没同步的不一致问题。
  • 列表操作的顺序要对:先修改内存中的数据源,再更新数据库,最后调用notify系列方法刷新UI,顺序错了会出现数据和UI不匹配的崩溃或显示异常。
  • 不要在onBindViewHolder里做全量数据查询,这个方法会在item滑入屏幕时频繁调用,冗余IO会严重影响列表滑动流畅度。
  • 删除操作不要直接用onBindViewHolder传入的position参数,用holder.getAdapterPosition()拿实时位置,避免列表动画过程中位置不准删错条目。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 15:18:15