自定义ExpandableListView适配器失效,无法获取子项数据
嘿,我来帮你搞定这个ExpandableListView子项数据获取失败的问题,咱们一步步拆解可能的原因和修复方案:
核心问题分析
你抛出异常的那行代码,本质上是在从HashMap中通过标题对象获取对应的子列表,再取指定位置的子项。这里最容易出问题的地方有3个:
1. HashMap键的匹配逻辑错误
你的expandableListDetail是以Products_With_ProfileModel作为键的HashMap,但如果这个类没有正确重写equals()和hashCode()方法,HashMap会默认用对象的引用地址来判断键是否相等。这就会导致:即使expandableListTitle.get(listPosition)和HashMap里的键对象内容完全一样,但只要是不同实例,就会返回null,后续调用get(expandedListPosition)就会直接抛出空指针异常。
修复方案:
给Products_With_ProfileModel类重写equals()和hashCode(),比如用唯一标识(比如user_id)来判断相等性:
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Products_With_ProfileModel that = (Products_With_ProfileModel) o; return Objects.equals(getUser_id(), that.getUser_id()); } @Override public int hashCode() { return Objects.hash(getUser_id()); }
2. 缺失空值与越界检查
当前代码直接链式调用expandableListDetail.get(...).get(...),完全没做任何空值判断:
- 如果
expandableListDetail中找不到对应键的子列表,会返回null - 如果
expandedListPosition超出了子列表的长度,会抛出索引越界异常
修复方案:
在getChild()和getChildView()中添加安全检查,以getChildView()为例修改:
// 修改之前的子项获取代码 Products_With_ProfileSubModel item = null; Products_With_ProfileModel groupItem = expandableListTitle.get(listPosition); List<Products_With_ProfileSubModel> childList = expandableListDetail.get(groupItem); if (childList != null && expandedListPosition >= 0 && expandedListPosition < childList.size()) { item = childList.get(expandedListPosition); } else { // 可以在这里做容错处理,比如返回默认的空对象,或者打印日志提示 Log.e("ExpandableAdapter", "子列表为空或索引越界:groupPosition=" + listPosition + ", childPosition=" + expandedListPosition); // 也可以直接返回row,避免崩溃 return row; } // 后续再使用item进行UI绑定 if (item != null) { holder.user_id.setText(item.getId()); holder.name.setText(item.getName()); // ... 其他Picasso加载逻辑 }
同样的,getChild()方法也需要添加类似的安全检查,避免返回null导致后续调用出错。
3. 数据一致性问题
确保expandableListTitle和expandableListDetail的数据是完全匹配的:
- 每个
expandableListTitle中的元素,在expandableListDetail中都有对应的非空子列表 getChildrenCount()方法返回的长度,必须和实际子列表的长度一致(当前代码虽然写了,但如果子列表为null会直接崩溃,所以要修改)
修复方案:
修改getChildrenCount()方法,添加空值判断:
@Override public int getChildrenCount(int listPosition) { List<Products_With_ProfileSubModel> childList = expandableListDetail.get(expandableListTitle.get(listPosition)); return childList != null ? childList.size() : 0; }
额外建议
- 调试时可以添加日志,打印
expandableListDetail.get(groupItem)的结果,看是否为null,以及子列表的长度,帮助定位问题 - 如果后续需要实现过滤功能,当前
getFilter()返回null的逻辑需要补充,否则过滤会失效
内容的提问来源于stack exchange,提问作者Brightcode Software Services P

