You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Room数据库提取数据列表遇问题:mDonorList为空,求正确实现方法

问题分析与解决方案

核心问题原因

  1. 列表未初始化+空安全调用失效:你将mDonorList初始化为null,协程内使用mDonorList?.add(item.id)时,因为列表是null,这行代码会直接跳过,根本不会添加任何元素。
  2. 协程异步执行导致逻辑顺序错误:lifecycleScope.launch是异步执行的,你在启动协程后立刻就执行checkduplicateId(mDonorList!!,Id),此时数据库查询还未完成,mDonorList仍为null,甚至会触发空指针异常。
  3. 错误使用数据流监听:如果只是一次性获取所有数据,不需要用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 18:10:29