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

如何通过代码一次性修改RecyclerView所有项,解决数据集超10个时长按崩溃问题

崩溃根因

你当前写法的问题完全出在对RecyclerView复用机制的错误使用上:findViewHolderForAdapterPosition()只能获取到当前屏幕可见(+少量预加载)的列表项对应的ViewHolder实例,超出屏幕的项没有可复用的ViewHolder,调用该方法会直接返回null,后续你没有做空判断就调用方法,必然触发空指针异常。
数据少于10项时刚好铺满一屏,所有项都有对应ViewHolder所以运行正常,数据量超过一屏后就会崩溃。


修复方案(完全保留原有交互逻辑)

不要直接遍历修改ViewHolder的视图状态,所有和列表项展示相关的逻辑都应该放到Adapter的onBindViewHolder中处理,符合RecyclerView的设计规范,无论多大数据集都不会出问题。

第一步:在RecyclerAdapter中新增状态变量

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {
    // 原有变量保留,新增以下两个变量
    // 标记当前是否处于删除选择模式
    private boolean isInDeleteMode = false;
    // 存储用户选中要删除的项位置,也可以换成存储单词id,根据你的业务调整
    private List<Integer> selectedDeletePositions = new ArrayList<>();

    // 新增两个变量的get/set方法
    public boolean isInDeleteMode() {
        return isInDeleteMode;
    }

    public void setInDeleteMode(boolean inDeleteMode) {
        isInDeleteMode = inDeleteMode;
        // 切换模式时清空选中状态
        selectedDeletePositions.clear();
    }

    public List<Integer> getSelectedDeletePositions() {
        return selectedDeletePositions;
    }

    // ... 原有其他代码保留
}

第二步:修改onBindViewHolder方法,添加删除模式相关的视图绑定逻辑

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
    // 你原本绑定单词数据的逻辑完全保留,以下是新增逻辑
    RadioButton deleteRb = holder.getView().findViewById(R.id.delete_selector);
    if (isInDeleteMode) {
        // 删除模式下显示单选按钮
        deleteRb.setVisibility(View.VISIBLE);
        deleteRb.setChecked(selectedDeletePositions.contains(position));
    } else {
        // 普通模式下隐藏单选按钮
        deleteRb.setVisibility(View.INVISIBLE);
        deleteRb.setChecked(false);
    }

    // 单选按钮的点击选中逻辑也放到这里处理
    deleteRb.setOnClickListener(v -> {
        if (selectedDeletePositions.contains(position)) {
            selectedDeletePositions.remove(Integer.valueOf(position));
        } else {
            selectedDeletePositions.add(position);
        }
        // 只刷新当前点击的项,性能更高
        notifyItemChanged(position);
    });
}

第三步:替换你原来的长按事件逻辑

删掉原来遍历所有ViewHolder的代码,替换为以下逻辑:

@Override
public void onLongItemClick(int adapterPosition) {
    // 切换删除模式状态
    adapter.setInDeleteMode(!adapter.isInDeleteMode());
    // 刷新所有可见项更新视图状态
    adapter.notifyItemRangeChanged(0, adapter.getItemCount());
    longClicked = adapter.isInDeleteMode();
}

第四步:删除数据逻辑补充

你需要执行删除操作时,直接从adapter.getSelectedDeletePositions()拿到所有选中的项,对应从你的数据源中取出单词数据删除Room数据库,删除完成后更新Adapter的数据源,调用notifyDataSetChanged()或者精准的notifyItemRemoved()即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 15:57:03