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

使用Kotlin Flow与Android RoomDB删除数据时的空指针错误解决

问题:删除RoomDB数据后触发空指针异常

删除RoomDB中的数据后出现如下错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String app.zimablue.artbookfragmentversion.model.ArtEntity.getArtName()' on a null object reference

推测原因是尝试访问已删除的数据——数据可正常删除,但删除后界面无数据可展示从而触发错误。已尝试检查art.name和art.artistName是否为空,也将数据库字段设为可空,但均未解决问题。


相关代码

Dao层代码

@Dao
interface ArtDao {
    @Insert
    suspend fun insert(artEntity: ArtEntity)
    @Delete
    suspend fun delete(artEntity: ArtEntity)
    @Query("SELECT * FROM `art-table`")
    fun getArtWithNameAndId():Flow<List<ArtEntity>>
    @Query("SELECT * FROM `art-table` WHERE id = :id")
    fun getArtById(id: Int): Flow<ArtEntity>
}

实体类代码

@Entity(tableName = "art-table")
class ArtEntity(
    @ColumnInfo(name = "name")
    @NonNull var artName : String,
    @NonNull @ColumnInfo(name = "artistname")
    var artistName: String,
    @NonNull @ColumnInfo(name = "year")
    var year : String,
    @NonNull @ColumnInfo(name = "image")
    var image : ByteArray
) {
    @PrimaryKey(autoGenerate = true)
    var id : Int = 0
}

报错指向代码

private fun oldArtDetails(art : ArtEntity){
    artFromMain = art
    art.artName.let {
        binding.artText.setText(it)
    }
    art.artistName.let {
        binding.artistText.setText(it)
    }
    art.year.let {
        binding.yearText.setText(it)
    }
    art.image.let {
        val bitmap = it.let {
            BitmapFactory.decodeByteArray(it,0, it.size) }
        binding.imageView.setImageBitmap(bitmap)
    }
}

解决方案

  1. 修复Dao查询的空值处理
    当前getArtById返回Flow<ArtEntity>,但对应ID的数据被删除后,查询结果会是null,而Flow无法发射null值,会导致下游接收异常。修改Dao方法,让其支持返回空值:

    @Query("SELECT * FROM `art-table` WHERE id = :id")
    fun getArtById(id: Int): Flow<ArtEntity?>
    
  2. 在调用oldArtDetails前添加空值判断
    确保传入方法的art参数不为null,在数据收集处处理空值场景:

    artDao.getArtById(artId).collect { art ->
        art?.let { oldArtDetails(it) } ?: run {
            // 数据为空时的处理逻辑,比如清空界面输入框、隐藏图片
            binding.artText.setText("")
            binding.artistText.setText("")
            binding.yearText.setText("")
            binding.imageView.setImageBitmap(null)
        }
    }
    
  3. 给oldArtDetails方法加空值防护
    即使外部做了判断,也可以在方法内部再加一层防护,避免意外传入null:

    private fun oldArtDetails(art : ArtEntity?){
        art ?: return // 若art为空,直接终止方法执行
        artFromMain = art
        art.artName.let { binding.artText.setText(it) }
        art.artistName.let { binding.artistText.setText(it) }
        art.year.let { binding.yearText.setText(it) }
        art.image.let {
            val bitmap = BitmapFactory.decodeByteArray(it,0, it.size)
            binding.imageView.setImageBitmap(bitmap)
        }
    }
    
  4. 实体类字段无需改为可空
    你的实体类设计中字段均为非空是合理的,因为数据库中存储的有效数据本应是完整的。空值问题出在查询结果的传递环节,而非实体字段本身。


内容的提问来源于stack exchange,提问作者Mert Parlak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 14:01:27