Room数据库提取数据列表遇问题:mDonorList为空,求正确实现方法
问题分析与解决方案
核心问题原因
- 列表未初始化+空安全调用失效:你将
mDonorList初始化为null,协程内使用mDonorList?.add(item.id)时,因为列表是null,这行代码会直接跳过,根本不会添加任何元素。 - 协程异步执行导致逻辑顺序错误:
lifecycleScope.launch是异步执行的,你在启动协程后立刻就执行checkduplicateId(mDonorList!!,Id),此时数据库查询还未完成,mDonorList仍为null,甚至会触发空指针异常。 - 错误使用数据流监听:如果只是一次性获取所有数据,不需要用
collect(它用于持续监听数据变化),直接获取单次查询结果即可。
修复后的代码
将所有逻辑放在同一个协程内,确保数据库查询完成后再做重复校验:
private fun addRecord(donorDao: DonorDao) { val id = binding?.etDonorId?.text.toString().trim() val bloodGr = binding?.etDonorBloodgroup?.text.toString().trim() if (id.isEmpty() || bloodGr.isEmpty()) { Toast.makeText(this, "输入不能为空", Toast.LENGTH_SHORT).show() return } lifecycleScope.launch { // 一次性获取所有捐赠者数据,无需持续监听 val allDonors = donorDao.fetchAllDonor().first() // 提取所有ID到ArrayList val donorIds = ArrayList(allDonors.map { it.id }) if (!donorIds.contains(id)) { donorDao.insert(DonorEntity(id = id, bloodGroup = bloodGr)) Toast.makeText(applicationContext, "记录保存成功", Toast.LENGTH_SHORT).show() } else { Toast.makeText(applicationContext, "ID重复!", Toast.LENGTH_SHORT).show() } } }
简化重复校验逻辑(可选)
原checkduplicateId函数可以直接用Kotlin内置方法替代,无需手动写循环:
private fun checkduplicateId(mDonorList: List<String>, id: String): Boolean { return !mDonorList.contains(id) }
Room提取数据到ArrayList的通用方法
根据你的Dao方法返回类型,选择对应方式:
- 如果Dao返回
Flow<List<DonorEntity>>:val donorList = ArrayList(donorDao.fetchAllDonor().first()) - 如果Dao返回挂起函数
List<DonorEntity>:val donorList = ArrayList(donorDao.fetchAllDonor())
额外注意事项
- 变量名遵循驼峰命名规范(如
Id改为id),提升代码可读性 - 输入处理时添加
trim(),避免前后空格导致的空字符串误判 - 避免使用
!!强制非空,优先用安全调用或提前做空判断,防止空指针异常
内容的提问来源于stack exchange,提问作者Dhruv pratap
相关产品推荐
相关产品推荐

