我遇到的问题是,在我的RecyclerView
上拖动项目时,onMove()
回调不能更改项目数组的实际顺序,因为该数组由{{1 }}。如果我在数据库上执行此操作,则会在后台线程上发生,因为PagedListAdapter
要求我执行此操作(无论如何,我确实应该在后台线程上执行数据库),并且可以想象,这不起作用拖动该项目时效果很好。
我对Room
的工作方式的理解是,在ItemTouchHelper
上,我必须重新排列想要显示的内容,然后才能保存到onMove()
上的DB中。但是我无法在clearView()
上重新排列。
这是我当前代码的简化,可以工作,但是拖动的视觉提示效果不好。
onMove()
那么我该如何使它在视觉上起作用?
谢谢。
答案 0 :(得分:0)
我假设您正在使用Room Database将分页数据加载到UI。实际上,如果使用分页库,那是使我们的列表能够响应数据动态变化的唯一方法。
在适配器中,您只需要通知数据库以更改onMove()函数
class SwipeCallback(
private val adapter: HomeSpotAdapter,
private val onItemMove: (from: Int, to: Int) -> Unit
) : ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper.RIGHT) {
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val from = viewHolder.adapterPosition
val to = target.adapterPosition
val item1 = adapter.getItem(from)
val item2 = adapter.getItem(to)
if (item1 != null && item2 != null) {
// Notify database to swap items here
onItemMove(from, to)
return true
}
return false
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
}
override fun isLongPressDragEnabled(): Boolean {
// It has to be true
return true
}
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
super.onSelectedChanged(viewHolder, actionState)
if (actionState == ACTION_STATE_DRAG) {
viewHolder?.itemView?.alpha = 0.5f
}
}
override fun clearView(recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
viewHolder.itemView.alpha = 1.0f
// Don't need to do anything here
}
}
在片段中,我们将onItemMove lambda函数传递给适配器
ItemTouchHelper(HomeSpotAdapter.SwipeCallback(adapter) { from, to ->
viewModel.swapItems(from, to)
}).apply {
attachToRecyclerView(recyclerView.getRecycler())
}
要交换数据库中的项目,基本上我们可以使用这样的swapItems()函数
fun swapItem(from: Int, to: Int) {
// I'm using executor to run query in worker thread here, but you can choose whatever you want
Executors.newSingleThreadExecutor().execute {
val item1 = db.HomeSpotDao().getSpot(from)
val item2 = db.HomeSpotDao().getSpot(to)
// Swap index of 2 items
val newItem1 = item1.copy()
newItem1.indexInResponse = item2.indexInResponse
val newItem2 = item2.copy()
newItem2.indexInResponse = item1.indexInResponse
db.HomeSpotDao().updateSpot(newItem1)
db.HomeSpotDao().updateSpot(newItem2)
}
}
您可以在Google示例中查看此类,以了解如何使用indexInResponse来跟踪列表中项目的索引
答案 1 :(得分:0)
最后找到了正确的解决方案。
在onMove
上,您必须notifyItemMoved(from,to)
,然后在clearView
上,实际上是在移动数据库。根据您所涉及的移动,您可能必须将第一个from
存储在notifyItemMoved
上,然后计算其移动位置to
,并修改数据库之间的所有时间。