3

我正在实现一个支持拖放的 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 以获得漂亮的动画。将不胜感激的建议。

4

1 回答 1

3

诀窍是更新ListAdapter你的项目ItemTouchHelper.Callback,以便从你的房间数据库更新什么都不做,因为项目已经相等。

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
    }

    ...
}
于 2020-07-01T12:42:47.890 回答