Kotlin中如何获取Android Room数据库插入行的自增ID?
报错根因
Room的@Insert注解原生不支持直接返回LiveData<Long>类型。LiveData是用于持续观察数据库变化的可观察容器,而单次插入属于一次性IO操作,Room没有为插入方法适配LiveData类型的返回值,因此抛出类型不支持的错误。
实现方案(无需额外依赖,适配LiveData)
你可以用Android官方原生协程配合LiveData构建器实现,当前AndroidX环境默认支持,不需要引入RxJava或其他额外依赖,修改步骤如下:
1. 修改Dao层代码
将返回值改为直接返回Long类型,用suspend关键字标记为挂起函数适配协程:
@Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun addUserWithLong(user: User): Long
2. 修改Repository层代码
用系统自带的liveData构建器把插入结果封装为LiveData:
fun addUserWithLong(user: User): LiveData<Long> = liveData { val rowId = userDao.addUserWithLong(user) emit(rowId) }
注:这里返回的Long类型rowId是SQLite的自增行ID,因为你的userId字段被标记为自增主键,所以该值和生成的userId完全相等,后续转Int即可拿到用户ID。
3. ViewModel层代码可保持不变
fun addUserWithLong(user: User): LiveData<Long> { return repository.addUserWithLong(user) }
4. 修改Fragment层调用逻辑
不能直接取LiveData的value,插入是异步操作,直接取值时结果还未生成,必须通过观察者回调拿结果:
userViewModel.addUserWithLong(user).observe(viewLifecycleOwner) { rowId -> val userId = rowId.toInt() // 此处即为生成的用户ID // 在这里执行拿到ID后的后续逻辑 }
额外说明
- 如果你的项目暂时不适用协程,可以把Dao层方法改为普通的返回Long的方法,自己在Repository中开子线程执行插入,再通过
MutableLiveData.postValue()把结果返回,同样可以实现需求。 - 如果触发
REPLACE冲突策略,返回的rowId是替换后的新行ID,对应最新的userId,符合预期。
内容的提问来源于stack exchange,提问作者Tbijo54
相关产品推荐
相关产品推荐

