Room Database单次取数空指针报错修复及allowMainThreadQueries利弊分析
问题1:空指针报错原因及修复方案
报错原因
核心触发原因有两个:
- DAO接口中
readUserByIdSyncDAO方法返回类型定义为不可空的UserModel,当数据库中不存在对应id的用户数据时,Room会直接返回null,Kotlin对不可空类型赋值null时会直接触发空指针异常。 UserModel实体类中的friends字段定义为不可空的ArrayList类型,若数据库中该字段存储的值为null,Room在反射构造UserModel实例时,会给不可空的friends字段赋值null,触发空指针。
修复方案
- 修改DAO接口的返回类型为可空类型:
@Query("select * from user_table where _id =:id") fun readUserByIdSyncDAO(id : String) : UserModel?
- 调整Repository、ViewModel层对应方法的返回值都适配可空类型,调用处增加空判断处理异常场景:
val userModel = viewModel.readUserByIdSyncDAO(userId) if (userModel != null) { Log.e(TAG,userModel.toString()) } else { // 自定义处理用户不存在的逻辑,比如弹提示、返回默认用户实例 }
- 检查
UserModel实体类定义,将允许为空的字段定义为可空类型,或给字段设置默认值:
// 方案1:定义为可空类型 val friends: ArrayList<String>? = null // 方案2:设置默认空集合 val friends: ArrayList<String> = arrayListOf()
问题2:allowMainThreadQueries()配置的利弊
该配置弊大于利,不建议在正式版本中使用:
- 数据库操作属于IO操作,即使是单次小查询,也存在IO阻塞的风险,主线程被阻塞会直接导致UI卡顿、掉帧,阻塞时长超过5秒还会触发ANR(应用无响应),严重影响用户体验。
- Room默认禁止主线程查询,就是强制开发者使用异步方案(比如Kotlin协程、RxJava、LiveData)执行数据库操作,避免阻塞主线程。
- 仅可在测试环境临时使用,正式环境必须移除该配置,改用异步方式实现数据库操作。
内容的提问来源于stack exchange,提问作者Lộc Trần Phước
相关产品推荐
相关产品推荐

