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

RecyclerView双不等长列表报错:java.lang.IndexOutOfBoundsException

问题解决方案

崩溃的核心原因是错误地用列表索引position关联员工和排班数据——两个列表长度不同,当position超出排班列表的长度时,调用allAvailabilitys.get(position)必然抛出IndexOutOfBoundsException。正确的关联逻辑应该是通过**员工ID(EID)**匹配对应的排班数据,而非依赖列表显示顺序的索引。

步骤1:重构适配器,通过员工ID匹配排班

将排班列表转换为以员工ID为Key的Map,避免每次遍历查找,提升效率,同时彻底摆脱对position的依赖:

public class RecycleViewAdapter extends RecyclerView.Adapter<RecycleViewAdapter.MyViewHolder> {
    List<EmployeeModel> allEmployees;
    // 替换List为Map,Key是员工EID,Value是对应排班
    private Map<Integer, AvailabilityModel> availabilityMap;
    Context context;

    public RecycleViewAdapter(List<EmployeeModel> allEmployees, List<AvailabilityModel> allAvailabilitys, Context context) {
        this.allEmployees = allEmployees;
        this.context = context;
        // 初始化排班Map
        availabilityMap = new HashMap<>();
        for (AvailabilityModel model : allAvailabilitys) {
            // 假设AvailabilityModel有getEID()方法,返回关联的员工ID
            availabilityMap.put(model.getEID(), model);
        }
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_view_employee, parent, false);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        EmployeeModel employee = allEmployees.get(position);
        // 通过员工ID获取对应排班,没有则创建空对象
        AvailabilityModel available = availabilityMap.get(employee.getEID());
        if (available == null) {
            // 创建默认空排班,参数根据你的AvailabilityModel构造函数调整
            available = new AvailabilityModel(-1, employee.getEID(), "", "", "", "", "", "", "");
        }

        // 绑定员工信息逻辑不变
        holder.employeeID.setText(String.valueOf(employee.getEID()));
        holder.firstName.setText(employee.getfName());
        holder.lastName.setText(employee.getlName());
        holder.employee = employee;

        // 按钮点击逻辑不变,注意传递的是匹配后的available对象
        holder.availabilityButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(context, availability_screen_code.class);
                intent.putExtra("Available", employee);
                intent.putExtra("Days", available);
                context.startActivity(intent);
            }
        });

        // 其他按钮逻辑保持不变...
    }

    @Override
    public int getItemCount() {
        return allEmployees.size();
    }

    // ViewHolder代码保持不变...
}

步骤2:调整排班页面的空数据处理

在availability_screen_code中,处理空排班的情况,避免因空字符串导致Spinner设置索引失败:

// 原代码中设置Monday Spinner的部分修改为:
String availableString = available.getMonday();
if (TextUtils.isEmpty(availableString)) {
    // 空数据时设置默认选中第一个选项
    mondaySpinner.setSelection(0);
} else {
    mondaySpinner.setSelection(getIndex(mondaySpinner, availableString));
}

同时,确保getIndex方法能处理空值(如果该方法是自定义的):

private int getIndex(Spinner spinner, String value) {
    if (TextUtils.isEmpty(value)) return 0;
    for (int i = 0; i < spinner.getCount(); i++) {
        if (spinner.getItemAtPosition(i).toString().equals(value)) {
            return i;
        }
    }
    return 0;
}

额外优化:数据库操作逻辑

在排班页面的确认按钮点击事件中,建议先判断该员工是否已有排班,再决定执行update还是add,避免重复插入数据:

confirmation.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        try{
            String mon = mondaySpinner.getSelectedItem().toString();
            String tue = tuesdaySpinner.getSelectedItem().toString();
            // ...其他日期变量
            
            EmployeeDBAssist employeeDBAssist = new EmployeeDBAssist(availability_screen_code.this);
            // 先检查是否已有排班
            boolean hasAvailability = employeeDBAssist.checkAvailabilityExists(employee.getEID());
            if (hasAvailability) {
                employeeDBAssist.updateAvailability(employee.getEID(), mon, tue, ...);
            } else {
                AvailabilityModel availabilityModel = new AvailabilityModel(-1, employee.getEID(), mon, tue, ...);
                employeeDBAssist.addAvailability(availabilityModel);
            }
            Toast.makeText(availability_screen_code.this, "排班设置成功", Toast.LENGTH_SHORT).show();
        } catch (Exception e){
            Toast.makeText(availability_screen_code.this, "Error Setting Availability", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
        Intent i = new Intent(availability_screen_code.this,activity_main_code.class);
        startActivity(i);
    }
});

(注:需要在EmployeeDBAssist中实现checkAvailabilityExists(int eid)方法,查询数据库中是否存在该员工的排班记录)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 17:35:23