Room数据库中为含ArrayList属性的实体新增数据出现死循环如何解决
问题根因
你触发死循环的核心原因是readUserByIdDAO返回的是LiveData<UserModel>类型,这类可观察对象只要对应数据库条目发生变更,就会触发observe的回调逻辑。你在回调内修改数据后调用了updateUserDAO更新数据库,导致LiveData再次感知到数据变化触发回调,进入无限循环。
解决方法
你可以根据自己的业务需求选择以下任意一种方案:
方案1:改用单次查询(最推荐)
如果你只是需要读取一次当前用户数据完成修改,不需要持续监听该用户的变化,直接给DAO新增单次挂起查询接口即可:
- 新增DAO方法:
@Query("select * from user_table where _id =:id") suspend fun readUserByIdOnce(id: String) : UserModel?
- 修改更新逻辑,在协程中完成「查-改-存」流程:
private fun updateFriend() { val friendId = "foo" lifecycleScope.launch { val currentUser = viewModel.readUserByIdOnce(userId) ?: return@launch // 防止重复添加好友ID if (!currentUser.friends.contains(friendId)) { currentUser.friends.add(friendId) viewModel.updateUserDAO(currentUser) } } }
方案2:在现有观察者逻辑中加校验
如果你确实需要持续监听该用户的数据变化,只需要在回调中增加更新前置判断,避免重复执行更新操作即可:
// 注意:观察者注册逻辑建议放到onCreate/onViewCreated等生命周期方法中,不要每次调用updateFriend都重复注册 private val userObserver = Observer<UserModel> { user -> val friendId = "foo" if (!user.friends.contains(friendId)) { user.friends.add(friendId) viewModel.updateUserDAO(user) } } // 初始化时注册观察者 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) viewModel.readUserByIdDAO(userId).observe(this, userObserver) } private fun updateFriend() { // 有更新需求时观察者会自动校验执行 }
额外优化建议
你的类型转换器返回的是ArrayList<String?>,但实体类friends字段声明的是ArrayList<String>,建议统一类型,避免后续出现空指针异常。
内容的提问来源于stack exchange,提问作者Lộc Trần Phước
相关产品推荐
相关产品推荐

