android - Android SortedList 拖动并重新排序项目抛出 IndexOutOfBoundsException:检测到不一致。无效的视图支架适配器 positionViewHolde
问题描述
我在使用sortedList实现回收视图时遇到问题。我需要为此回收视图实现拖动和重新排序功能,我使用“ItemTouchHelper.Callback()”来处理向上/向下移动
class SimpleItemTouchHelperCallback(private val mAdapter: ItemTouchHelperAdapter) :
ItemTouchHelper.Callback() {
override fun onMove(
recyclerView: RecyclerView,
source: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
if (source.itemViewType != target.itemViewType) {
return false
}
val fromPosition = source.adapterPosition
val toPosition = target.adapterPosition
dragFrom = fromPosition
dragTo = toPosition
Timber.d(">> SimpleItemTouchHelperCallback ->>> onMove fromPosition = $fromPosition | toPosition = $toPosition")
// Notify the adapter of the move
mAdapter.onItemMove(dragFrom, dragTo)
return true
}
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
viewHolder.itemView.alpha = ALPHA_FULL
if (viewHolder is ItemTouchHelperViewHolder) {
// Tell the view holder it's time to restore the idle state
val itemViewHolder = viewHolder as ItemTouchHelperViewHolder
itemViewHolder.onItemClear()
// To detect when an interaction with an element is over
if (dragFrom != -1 && dragTo != -1 && dragFrom != dragTo) {
mAdapter.dragAndDropCompleted(dragFrom, dragTo)
}
dragFrom = -1
dragTo = -1
}
}
}
//===========
class ShoppingListRecyclerListAdapter(
private val onItemClickListener: OnItemClickListener,
private val userCheckedInToStore: Boolean
) : RecyclerView.Adapter<BaseShoppingListViewHolder>(), ItemTouchHelperAdapter {
private var sortedItemList: SortedList<ShoppingListEntry>
override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean {
var dragFromItem = sortedItemList[fromPosition]
var dragToItem = sortedItemList[toPosition]
if (dragFromItem is UnCheckedFreeTextItem && dragToItem is UnCheckedFreeTextItem) {
val dragFromItemSortIndex = dragFromItem.freeTextShoppingItem.sortIndex
val dragFromItemName = dragFromItem.freeTextShoppingItem.itemName
dragFromItem.freeTextShoppingItem.sortIndex =
dragToItem.freeTextShoppingItem.sortIndex
dragToItem.freeTextShoppingItem.sortIndex = dragFromItemSortIndex
dragToItem.modify = true
dragFromItem.modify = true
dragFromItem.freeTextShoppingItem.itemName =
dragToItem.freeTextShoppingItem.itemName
dragToItem.freeTextShoppingItem.itemName = dragFromItemName
dragItemSet.add(dragToItem)
dragItemSet.add(dragFromItem)
sortedItemList.beginBatchedUpdates()
//sortedItemList.recalculatePositionOfItemAt(fromPosition)
sortedItemList.updateItemAt(fromPosition, dragFromItem)
//sortedItemList.recalculatePositionOfItemAt(toPosition)
sortedItemList.updateItemAt(toPosition, dragToItem)
//sortedItemList.recalculatePositionOfItemAt(fromPosition)
//sortedItemList.recalculatePositionOfItemAt(toPosition)
//sortedItemList.updateItemAt(fromPosition, dragToItem)
sortedItemList.endBatchedUpdates()
}
}
}
当用户长按一个项目并开始移动时出现异常
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{c026f4 position=6 id=39, oldPos=6, pLpos:-1 scrap [attachedScrap]
tmpDetached no parent} androidx.recyclerview.widget.RecyclerView{1991c2a VFED.V... ......ID 0,364-1080,1980 #7f0a01db app:id/shoppingListView},
adapter:com.adingk.lib.ui.shoppinglist.ShoppingListRecyclerListAdapter@741fa1b, layout:androidx.recyclerview.widget.LinearLayoutManager@d2de7b8,
context:com.adingk.lib.ui.shoppinglist.ManageShoppingListActivity@76ea334
at androidx.recyclerview.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5715)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5898)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5858)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5854)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2230)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1557)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1517)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:612)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:3875)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3639)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4194)
at android.view.View.layout(View.java:21927)
at android.view.ViewGroup.layout(ViewGroup.java:6260)
解决方案
而不是使用updateItemAt
try to use notifyItemMoved(fromPosition, toPosition)
which is 提供的方法RecyclerView.Adapter
。
override fun onItemMove(fromPosition: Int, toPosition: Int) {
notifyItemMoved(fromPosition, toPosition)
}
推荐阅读
- javascript - jQuery:页面的初始加载没有找到元素,但是当发生调整大小时,找到了元素。
- amp-html - 为什么 AMP 符号不显示在移动搜索中?
- intellij-idea - 如何轻松地将字符插入 IntelliJ 的编辑器
- cakephp-1.3 - 调用数组上的成员函数 func()
- java - 创建模型类并获取子节点内的数据
- ios - Xamarin 形式:使用 MediaPlugin 拍照。图像未显示为裁剪后拍摄的内容
- javascript - 有条件地向对象添加键值javascript
- python - pyside2/pyqt5 python 用户的 Qt Quick Creator (QML)
- vb.net - 无法使用 vb.net 将数据网格更新为 dbf
- javascript - 固定 div 浮动在另一个 div 上导致 scrollIntoView 在 angular2/4/5 中过冲,我该如何解决?