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
相关产品推荐
相关产品推荐

