RecyclerView侧滑删除后数据库删除错误问题排查与解决
解决RecyclerView侧滑删除后数据库删错数据的问题
问题根源
你当前代码的错误在于:侧滑后先调用adapter.removeItem(cachedPosition)把元素从列表中移除,此时listArray已经发生了变化。当Snackbar自动消失(用户未点击撤销)时,调用adapter.deleteFromDB(dbManager, cachedPosition),此时listArray[cachedPosition]对应的已经不是你要删除的那个元素了,导致传入数据库的id错误,最终删错数据。
最优方案选择
你的两种思路里,无需先删数据库再删列表,也不需要修改现有数据库删除函数(它本身是正确的,通过id删除是可靠的)。核心要改的是:删除数据库时直接使用缓存的待删除元素的id,而不是依赖列表当前的位置。
具体修改步骤
1. 调整MainActivity中的Snackbar回调逻辑
把删除数据库的操作改成直接用缓存的cachedItem的id,不需要通过Adapter的位置去取:
Snackbar.make(binding.rv, "Deleted", Snackbar.LENGTH_SHORT) .setAction("Undo") { } .addCallback(object: BaseTransientBottomBar.BaseCallback<Snackbar>() { override fun onDismissed(transientBottomBar: Snackbar, event: Int) { if (event == DISMISS_EVENT_ACTION) { adapter.restoreItem(cachedPosition, cachedItem) // 恢复后重新计算总和,保证金额显示正确 val b = dbManager.total().toBigDecimal().setScale(2, RoundingMode.HALF_UP).toString() binding.tvResult.text = "Сумма $b ₾" } else { // 直接用缓存元素的id删除数据库数据,完全不受列表变化影响 dbManager.removeItem(cachedItem.id.toString()) } } }) .show()
2. 删除Adapter中多余的deleteFromDB函数
现在直接在MainActivity里调用dbManager.removeItem即可,Adapter里的这个函数可以删掉,避免后续误用:
// 删掉以下无用函数 // fun deleteFromDB (dbManager: DbManager, pos: Int){ // dbManager.removeItem(listArray[pos].id.toString()) // }
方案优势
- 保留原有的“先删列表、延迟删数据库”流程,撤销操作只需要恢复列表,无需操作数据库,逻辑更简洁
- 直接用缓存元素的id删除数据库,完全不受列表位置变化的影响,从根源避免删错数据
- 现有数据库的
removeItem函数无需修改,通过主键id删除是最可靠的数据库操作方式
内容的提问来源于stack exchange,提问作者Антон Кузнецов
相关产品推荐
相关产品推荐

