我最终实现了一个新的适配器并使用它而不是 ListAdapter,如上所述马丁·马可尼尼的回答 https://stackoverflow.com/a/68452428/10833325。我添加了两个单独的函数。一个用于从 Room 数据库接收更新(替换submitList
来自 ListAdapter),另一个用于拖动时的每个位置变化
MyListAdapter.kt
class MyListAdapter(list: ArrayList<Item>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
// save instance instead of creating a new one every submit
// list to save some allocation time. Thanks to Martin Marconcini
private val diffCallback = DiffCallback(list, ArrayList())
fun submitList(updatedList: List<Item>) {
diffCallback.newList = updatedList
val diffResult = DiffUtil.calculateDiff(diffCallback)
list.clear()
list.addAll(updatedList)
diffResult.dispatchUpdatesTo(this)
}
fun itemMoved(from: Int, to: Int) {
Collections.swap(list, from, to)
notifyItemMoved(from, to)
}
}
DiffCallback.kt
class DiffCallback(
val oldList: List<Item>,
var newList: List<Item>
) : DiffUtil.Callback() {
override fun getOldListSize(): Int {
return oldList.size
}
override fun getNewListSize(): Int {
return newList.size
}
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = oldList[oldItemPosition]
val newItem = newList[newItemPosition]
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = oldList[oldItemPosition]
val newItem = newList[newItemPosition]
return compareContents(oldItem, newItem)
}
}
Call itemMoved
每个位置的变化:
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val from = viewHolder.bindingAdapterPosition
val to = target.bindingAdapterPosition
itemListAdapter.itemMoved(from, to)
// Update database as well if needed
return true
}
当从 Room 数据库接收更新时:
您可能还想检查当前是否使用拖动选定更改时 https://developer.android.com/reference/androidx/recyclerview/widget/ItemTouchHelper.Callback#onSelectedChanged(androidx.recyclerview.widget.RecyclerView.ViewHolder,%20int)如果您还更新数据库,则每个位置都会发生变化,以防止不必要的调用submitList
list.observe(viewLifecycleOwner, { updatedList ->
listAdapter.submitList(updatedList)
})