Android Adapter中调用Checkbox.isChecked()返回空指针问题求助
根因分析
你代码出现空指针的核心原因是不应该在数据类CategoryChild中直接存储CheckBox视图实例,具体触发空指针的场景分以下几种:
- RecyclerView的item只有渲染到屏幕上时才会执行
onBindViewHolder,你遍历的所有CategoryChild里,那些没在屏幕上显示的条目,setCheckBox从来没被调用过,内部的checkBox变量自然是null - RecyclerView会复用ViewHolder,滑动过程中同一个CategoryChild实例绑定的CheckBox实例可能被替换、甚至解绑,随时可能变为null
performFiltering是运行在后台子线程的,你直接在子线程访问UI控件CheckBox本身就不符合Android线程规则,即使CheckBox不为空也可能引发其他UI线程异常- 你在子Adapter的点击事件里添加checkedSubList、uncheckedSubList时,是新建了CategoryChild实例:
new CategoryChild(childItem.getCategoryAttribute()),这些新实例的checkBox变量完全没有初始化,只要调用getCheckBoxState必然空指针
修复方案
第一步:重构CategoryChild数据类,移除UI相关逻辑,单独用布尔变量存选中状态
public class CategoryChild { private String checkBoxText; // 单独用布尔值存选中状态,不要存CheckBox实例 private boolean isChecked; public CategoryChild(String categoryAttribute) { this.checkBoxText = categoryAttribute; // 默认未选中 this.isChecked = false; } public String getCategoryAttribute() { return checkBoxText; } public void setCategoryAttribute(String categoryAttribute) { this.checkBoxText = categoryAttribute; } public boolean isChecked() { return isChecked; } public void setChecked(boolean checked) { isChecked = checked; } }
第二步:修改子Adapter的绑定和点击逻辑,同步更新数据类的选中状态
@Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { CategoryChild childItem = childItemArrayList.get(position); holder.checkBox.setText(childItem.getCategoryAttribute()); // 直接用数据类的状态设置CheckBox,不要给数据类存CheckBox holder.checkBox.setChecked(childItem.isChecked()); holder.checkBox.setOnClickListener(v -> { boolean newState = holder.checkBox.isChecked(); // 先更新数据类的状态 childItem.setChecked(newState); if (newState) { checkedSubList.add(childItem); deleteChidList(uncheckedSubList, childItem.getCategoryAttribute()); containsChecked = true; } else { uncheckedSubList.add(childItem); deleteChidList(checkedSubList, childItem.getCategoryAttribute()); } // 不需要调用notifyDataSetChanged刷新整个列表,当前CheckBox状态已经和数据同步了 }); }
第三步:修改Filter中的状态获取逻辑,直接读数据类的布尔值,不要访问UI控件
for(CategoryChild child: parent.getChildViewList()) { // 直接读数据类里存的isChecked,不会有空指针 System.out.println(child.getCategoryAttribute() + " has the Checkbox State: " + child.isChecked()); if(child.isChecked()) { checkedChildList.add(child); } // 后面的逻辑你自己补充就行 }
额外优化点
- 你现在点击事件里重复调用
setChecked属于冗余逻辑,点击CheckBox本身就会自动切换选中状态,不需要手动再设置 - 不要在
performFiltering里修改全局的checkedValues、uncheckedValues集合,Filter的工作逻辑是只返回过滤后的结果,不要修改源数据避免并发问题 - 删除子列表元素的方法
deleteChidList遍历的时候直接调用remove会导致索引错乱,建议改用迭代器遍历删除,或者倒序遍历
内容的提问来源于stack exchange,提问作者Zeruma
相关产品推荐
相关产品推荐

