Android Kotlin获取RecyclerView选中复选框值报空指针异常
Android复选框联动崩溃修复与实现方案
崩溃根因
点击按钮触发空指针的核心原因有两个:
- Adapter伴生对象中定义的
selectedCheckboxes仅声明了可空类型,从未做初始化,使用!!强制调用clear()方法时直接触发空指针 - 原有在
onBindViewHolder中维护选中项列表的写法本身存在设计缺陷:RecyclerView的复用机制会导致onBindViewHolder重复触发,会出现选中项重复添加、误删的问题,即使初始化了变量也会出现数据错乱。
另外isAllItemsSameStatus方法中存在分类筛选逻辑错误:子列表筛选条件写为it.category == it.category(恒为真),会导致课程分类联动状态判断错误。
修复步骤
1. 替换按钮点击逻辑,移除冗余选中列表维护
不需要额外维护全局选中列表,直接从Adapter持有的数据源中筛选选中项即可,从根源避免空指针。
将Activity中按钮点击代码替换为:
findViewById<Button>(R.id.showTextBtn).setOnClickListener { val selectedSubjects = adapter.productList .filter { it.rowType == RowType.SubjectRow && it.isChecked } .map { it.subjectName } val checkboxesValue = selectedSubjects.joinToString(separator = ";") findViewById<TextView>(R.id.ShowTextView).text = checkboxesValue }
2. 清理Adapter中冗余代码
- 删除Adapter伴生对象中的
selectedCheckboxes声明 - 删除
onBindViewHolder末尾在绑定阶段增删选中项、弹出Toast的冗余代码块 - 修复
isAllItemsSameStatus方法中的筛选逻辑错误,将子列表筛选代码改为:
val subList = productList.filter { it.category == cat && it.rowType == RowType.SubjectRow }
使用string-array资源替换硬编码数据
1. 新建数组资源文件
在res/values/路径下新建arrays.xml,写入分类与学科配置:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="all_courses">All Courses</string> <!-- 各分类对应学科列表 --> <string-array name="Science"> <item>Physics</item> <item>Math</item> <item>Chemistry</item> </string-array> <string-array name="Arts"> <item>Economics</item> <item>History</item> <item>Political Science</item> </string-array> <string-array name="Commerce"> <item>Accountancy</item> <item>Business Studies</item> <item>Physical Education</item> </string-array> <!-- 分类名称列表 --> <string-array name="course_categories"> <item>Science</item> <item>Arts</item> <item>Commerce</item> </string-array> </resources>
2. 动态生成列表数据
替换Activity中原先硬编码的列表初始化逻辑,从资源文件读取数据生成列表:
val list = mutableListOf<RowModel>() // 添加顶部全选项 list.add(RowModel(RowType.TopHeader, "", "", false)) // 读取分类列表 val categories = resources.getStringArray(R.array.course_categories) categories.forEach { category -> // 添加课程分类项 list.add(RowModel(RowType.Course, "", category, false)) // 读取分类下对应学科 val subjectResId = resources.getIdentifier(category, "array", packageName) val subjects = resources.getStringArray(subjectResId) subjects.forEach { subject -> list.add(RowModel(RowType.SubjectRow, subject, category, false)) } }
优化建议
- 统一
RowModel中isChecked的默认值,避免初始化状态与预期不符 - 不要在Adapter伴生对象中存储页面相关的状态数据,容易引发内存泄漏与状态不同步问题,所有状态以数据源为准
- 列表项更新时尽量使用
notifyItemChanged的payload重载,避免全量绑定导致的监听重复触发问题
内容的提问来源于stack exchange,提问作者CHETAN
相关产品推荐
相关产品推荐

