RecyclerView滑动删除Firestore数据遇索引越界问题求助
滑动RecyclerView条目删除Firestore数据时的索引越界与联动问题解决
问题现象
- 滑动顶部条目时,底部条目会跟随滑动,但仅顶部条目从Firestore中被删除
- 滑动底部条目时触发索引越界错误:
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
核心问题分析
- 异步操作导致数据源不一致:Firestore删除是异步任务,若用户快速滑动多个条目,旧的回调会拿着已失效的
position操作修改后的foodList,直接引发索引越界 - 缺少视图状态重置:滑动结束后未恢复ViewHolder的初始状态,导致条目出现联动滑动异常
- 未处理删除失败的回滚:删除失败时,RecyclerView的条目已被划走,但数据源未更新,进一步加剧显示混乱
修复后的完整代码
1. 更新SwipeToDeleteCallback抽象类
abstract class SwipeToDeleteCallback : ItemTouchHelper.Callback() { override fun getMovementFlags( recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder ): Int { val swipeFlag = ItemTouchHelper.LEFT return makeMovementFlags(0, swipeFlag) } override fun onMove( recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder ): Boolean { return false } // 滑动结束后重置视图状态,解决联动滑动问题 override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) { super.clearView(recyclerView, viewHolder) ItemTouchHelper.Callback.getDefaultUIUtil().clearView(viewHolder.itemView) } // 限制滑动触发阈值,避免误操作 override fun getSwipeThreshold(viewHolder: RecyclerView.ViewHolder): Float { return 0.5f } }
2. 修复Fragment中的删除回调逻辑
val swipeToDeleteCallback = object : SwipeToDeleteCallback() { override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { val position = viewHolder.bindingAdapterPosition // 先校验位置有效性,直接拦截无效操作 if (position < 0 || position >= foodList.size) { feedAdapter.notifyItemChanged(position) return } // 提前缓存目标数据,避免异步过程中数据源变化导致的错误 val targetDocId = foodList[position].docId // 禁用视图防止重复触发删除 viewHolder.itemView.isEnabled = false firestore.collection("Foods").document(targetDocId).delete() .addOnSuccessListener { foodList.removeAt(position) feedAdapter.notifyItemRemoved(position) Toast.makeText(requireContext(), "Deleted", Toast.LENGTH_LONG).show() } .addOnFailureListener { e -> // 删除失败时恢复条目显示 feedAdapter.notifyItemChanged(position) Toast.makeText(requireContext(), e.localizedMessage, Toast.LENGTH_LONG).show() } .addOnCompleteListener { // 无论结果如何,恢复视图可交互状态 viewHolder.itemView.isEnabled = true } } } val itemTouchHelper = ItemTouchHelper(swipeToDeleteCallback) itemTouchHelper.attachToRecyclerView(binding.recyclerView)
关键修复点说明
- 位置有效性校验:操作前判断
position是否在foodList的合法范围内,直接拦截无效操作 - 缓存目标数据:异步操作前先获取要删除的文档ID,不依赖后续可能变化的数据源
- 删除失败回滚:调用
notifyItemChanged将划走的条目恢复,保证视图与数据源一致性 - 视图状态重置:通过
clearView方法确保滑动结束后视图回到初始状态,解决联动滑动问题 - 防止重复操作:滑动后禁用条目,避免用户重复触发删除逻辑
内容的提问来源于stack exchange,提问作者Mobile Development
相关产品推荐
相关产品推荐

