android - 带有 Room 的 PagedListAdapter 和 ItemTouchHelper - 在 onMove() 期间如何更新
问题描述
我遇到的问题是,在我的 上拖动项目时RecyclerView
,onMove()
回调无法更改项目数组的实际顺序,因为该数组由PagedListAdapter
. 如果我在 DB 上执行此操作,这将在后台线程上发生,因为Room
需要我这样做(而且我真的应该在后台线程上执行 DB),并且正如您可以想象的那样,这不适用于拖动该项目。
我对工作原理的理解ItemTouchHelper
是,onMove()
我必须重新排列我想要在视觉上显示的任何内容,然后我可以保存到数据库中clearView()
。但我无法重新排列onMove()
。
这是我当前代码的简化,它可以工作,但拖动的视觉提示效果不佳。
inner class SwipeCallback() : ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP or ItemTouchHelper.DOWN, ItemTouchHelper.RIGHT) {
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
val item1 = getItem(viewHolder.adapterPosition)
val item2 = getItem(target.adapterPosition)
if (item1 != null && item2 != null) {
//BASICALLY JUST SWAPPING THE TWO POSITIONS ON THE OBJECTS but not doing anything with the adapter array because the PagedListAdapter doesn't allow me to modify the array as far I know.
swapItems(item1,item2)
}
return true
}
return false
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun isLongPressDragEnabled(): Boolean {
return false
}
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
//THIS IS WHERE I UPDATED THE DB, currentList is the PagedListAdapter array. This is an inner class of my PagedListAdapter.
currentList?.let {updateList(it) }
}
}
那么我怎样才能使这项工作在视觉上呢?
谢谢。
解决方案
更新:我在这里创建了一个示例
我假设您正在使用 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 Sample 中的此类以了解如何使用 indexInResponse 来跟踪列表中项目的索引
推荐阅读
- .net - Dotfuscator 一遍又一遍地重复 SetStateMachine 和 MoveNext 警告
- netlogo - 扩展异常。Python 无法启动
- gstreamer - 通过 Gstreamer 将 VNC 转换为 RTSP
- html - SVG路径删除交点
- javascript - 如何将 Selenium 鼠标移动到精确的 X、Y 而不告诉必须使用 Javascript/Typescript 单击哪个元素?
- javascript - 将数量减少到 0 时删除确认对话框(Prestashop 1.7)
- amazon-web-services - SCP 没有这样的文件或目录
- python - 部署一个基本的 python sanic webserver
- google-api-nodejs-client - 如何在多工作人员环境中获取和使用访问令牌?
- c++ - 我的 IDE 或代码有问题吗?