Android Room数据库查询触发NullPointerException且DB BROWSER无表问题求助
错误原因
1. 空指针异常原因
你在Dao层定义的getAllUsers()返回类型是LiveData<List<User>>,LiveData是基于观察者模式的异步数据容器,未主动订阅Observer时不会触发数据库查询操作,其value属性初始默认值为null。你在协程中直接调用getAllUsers().value后用!!强制非空拆箱,触发了空指针,对应日志里的MainActivity.kt第39行报错。
2. DB Browser无数据/无表原因
Room默认开启WAL(预写日志)机制,所有写入操作会先写入xxx.db-wal日志文件,不会实时同步到主.db文件。你导出数据库时只拷贝了主db文件,未同步拷贝同目录下的.db-shm、.db-wal两个辅助文件,打开主db文件自然看不到最新的表结构和写入数据。
解决方案
1. 修复空指针异常
方案1(推荐,适合同步查询场景)
将Dao层的查询方法改为挂起函数,直接返回列表而非LiveData:
@Query("SELECT * FROM Users_Information ORDER BY id ASC") suspend fun getAllUsers():List<User>
修改btn2的点击逻辑,直接调用挂起函数获取数据:
btn2.setOnClickListener { lifecycleScope.launch(Dispatchers.IO) { val list = UserDB.getDatabase(applicationContext).dao().getAllUsers() list.forEach { Log.d("awawd", it.name) } } }
方案2(适合需要监听数据变化的场景)
保留LiveData返回类型,在主线程订阅Observer获取数据:
btn2.setOnClickListener { UserDB.getDatabase(applicationContext).dao().getAllUsers().observe(this) { list -> list.forEach { Log.d("awawd", it.name) } } }
2. 修复DB Browser看不到数据问题
导出数据库时,将内部存储data/data/[你的包名]/databases/目录下的三个文件全部导出到本地同一文件夹:
- PLEASE
- PLEASE-shm
- PLEASE-wal
再用DB Browser打开PLEASE主文件即可看到完整的表结构和数据。
额外注意事项
- 尽量避免使用
GlobalScope启动协程,改用lifecycleScope绑定Activity生命周期,避免页面销毁后协程继续执行引发内存泄漏。 - 生产环境不要使用
allowMainThreadQueries()允许主线程操作数据库,避免界面卡顿。
内容的提问来源于stack exchange,提问作者mo_nawas
相关产品推荐
相关产品推荐

