由于 ItemTouchHelper 和 DiffUtil 之间的冲突导致不需要的动画

Unwanted animation due to conflict between ItemTouchHelper and DiffUtil

我正在实现一个支持拖放的 RecyclerView。当一个项目被删除时,该项目的索引列将在 Room 数据库中更新以存储更新的排序。

我面临的问题是,当我在删除项目后调用 Room 数据库更新时,因为项目列表是 ViewModel 中的 LiveData 并通过 Databinding 绑定到 RecyclerView,DiffUtil 将重新计算项目位置和内容紧随其后,1. 添加了新的不需要的动画和 2. 有时内容没有正确刷新。

ItemTouchHelper:

val helper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(
    ItemTouchHelper.UP or ItemTouchHelper.DOWN or
            ItemTouchHelper.START or ItemTouchHelper.END, 0
) {

    var dragFrom = -1
    var dragTo = -1

    override fun onMove(
        recyclerView: RecyclerView, selected: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        val from = selected.adapterPosition
        val to = target.adapterPosition

        if (dragFrom == -1) {
            dragFrom = from
        }
        dragTo = to
        recyclerView.adapter?.notifyItemMoved(from, to)

        return true
    }

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
    }

    override fun clearView(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder
    ) {

        if (dragFrom != -1 && dragTo != -1 && dragFrom != dragTo) {
            val fromId = myAdapter.getItemId(dragFrom)

            detailViewModel.updateItemIndex(fromId, calcNewIndex(dragFrom, dragTo))
        }

        super.clearView(recyclerView, viewHolder)
        dragFrom = -1
        dragTo = -1
    }
})
helper.attachToRecyclerView(binding.detailRecyclerview)

MyAdapter 中的 DiffUtil:

class NoteDiffCallback : DiffUtil.ItemCallback<MyNote>() {
    override fun areItemsTheSame(oldItem: MyNote, newItem: MyNote): Boolean {
        return oldItem.noteId == newItem.noteId
        //return true (replacing this will mostly fix the ItemTouchHelper issues, but also removes other animations that I want, such as inserting)
    }

    override fun areContentsTheSame(oldItem: MyNote, newItem: MyNote): Boolean {
        return oldItem == newItem
    }
}

我想更改它以使 DiffUtil 不干扰 ItemTouchHelper,但我仍想保留 DiffUtil 以在插入新笔记时获得漂亮的动画效果。将不胜感激。

诀窍是更新 ItemTouchHelper.Callback 中的 ListAdapter 项,这样来自 Room 数据库的更新不会执行任何操作,因为这些项已经相等。

class ItemTouchHelperCallback(val adapter: MyNoteAdapter) :
        ItemTouchHelper.Callback() { // you need a reference to your adapter

    ...
    
    override fun onMove(
        recyclerView: RecyclerView, selected: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        val from = selected.adapterPosition
        val to = target.adapterPosition

        if (dragFrom == -1) {
            dragFrom = from
        }
        dragTo = to
    
        val items = adapter.currentList.toMutableList()
        Collections.swap(items, from, to)
        adapter.submitList(items) // calls adapter.notifyItemMoved(), so we don't have to

        return true
    }

    ...
}