Dan*_*aga 8 android listadapter android-recyclerview
我有一个从房间数据库更新的列表。我从 Room 收到更新后的数据作为新列表,然后将其传递给ListAdapter以submitList
获取更改的动画。
list.observe(viewLifecycleOwner, { updatedList ->
listAdapter.submitList(updatedList)
})
Run Code Online (Sandbox Code Playgroud)
现在,我想为同一个 RecyclerView 添加拖放功能。我尝试使用它来实现它ItemTouchHelper
。但是,notifyItemMoved()
由于 ListAdapter 通过 更新其内容,因此无法正常工作submitList()
。
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder
): Boolean {
val from = viewHolder.bindingAdapterPosition
val to = target.bindingAdapterPosition
val list = itemListAdapter.currentList.toMutableList()
Collections.swap(list, from, to)
// does not work for ListAdapter
// itemListAdapter.notifyItemMoved(from, to)
itemListAdapter.submitList(list)
return false
}
Run Code Online (Sandbox Code Playgroud)
拖放现在可以正常工作,但只有在缓慢拖动时,当拖动足够快时,我会得到不同且不一致的结果。
这可能是什么原因?为使用 ListAdapter 的 RecyclerView 实现拖放功能的最佳方法是什么?
我最终实现了一个新的适配器并使用它代替 ListAdapter,正如Martin Marconcini 的回答中提到的。我添加了两个单独的函数。一个用于接收来自 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)
}
}
Run Code Online (Sandbox Code Playgroud)
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)
}
}
Run Code Online (Sandbox Code Playgroud)
调用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
}
Run Code Online (Sandbox Code Playgroud)
当从 Room 数据库接收更新时:
如果您还在每次位置更改时更新数据库以防止不必要的调用,您可能还想检查当前是否使用onSelectedChanged进行拖动submitList
list.observe(viewLifecycleOwner, { updatedList ->
listAdapter.submitList(updatedList)
})
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3297 次 |
最近记录: |