使用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) } }
解决方案
修复Dao查询的空值处理
当前getArtById返回Flow<ArtEntity>,但对应ID的数据被删除后,查询结果会是null,而Flow无法发射null值,会导致下游接收异常。修改Dao方法,让其支持返回空值:@Query("SELECT * FROM `art-table` WHERE id = :id") fun getArtById(id: Int): Flow<ArtEntity?>在调用
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) } }给
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) } }实体类字段无需改为可空
你的实体类设计中字段均为非空是合理的,因为数据库中存储的有效数据本应是完整的。空值问题出在查询结果的传递环节,而非实体字段本身。
内容的提问来源于stack exchange,提问作者Mert Parlak
相关产品推荐
相关产品推荐

