如何顺利更改回收站视图项目
how to change recycler view items smoothly
我的布局中有一个回收视图,首先它会被存储在本地数据库中的数据填充,然后几秒钟后它会使用服务器更新。
问题是在更新的时候,recycler view 的项目突然改变了,我怎样才能为 recycler view 设置一个平滑改变项目的动画?
我像这样通知我的回收站视图:
fun add(list: List<BestStockModel>) {
items.clear()
items.addAll(list)
notifyItemRangeChanged(0, list.size)
}
有更好的方法,您可以使用 ListAdapter
link。
使用 ListAdapter
您可以简单地提交一个新列表,适配器将计算新旧列表之间的差异,并为 new/changed/deleted 项添加需要的动画。
它可以使用您提供给它的简单回调来检测差异。
下面是一个示例,您可以将其用作参考:
class HomeMoviesAdapter : ListAdapter<Movie, MoviesViewHolder>(
//note the following callbacks, ListAdapter uses them
// in order to find diff between the old and new items.
object : DiffUtil.ItemCallback<Movie>() {
override fun areItemsTheSame(oldItem: Movie, newItem: Movie): Boolean =
oldItem.title == newItem.title //this can be a unique ID for the item
override fun areContentsTheSame(oldItem: Movie, newItem: Movie): Boolean =
oldItem == newItem
}
) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MoviesViewHolder {
val v: View = LayoutInflater.from(parent.context)
.inflate(R.layout.movies_item_view, parent, false)
return MoviesViewHolder(v)
}
override fun onBindViewHolder(holder: MoviesViewHolder, position: Int) {
//your binding logic goes here as usual.
}
}
然后从您拥有列表的地方(例如:片段),您可以执行以下操作:
adapter.submit(newList)
这就是列表适配器为您制作所需动画的全部内容。
不过有一个问题:如果提交相同的列表引用,适配器会认为它与旧列表相同,这意味着它不会触发差异计算。请注意以下示例:
//the following is a bad practice DO NOT do this!
val list: MutableList<Int> = mutableListOf(1, 2, 3)
adapter.submitList(list)
list.clear()
list.add(7)
adapter.submitList(list) //nothing will happen, since it's the same ref
将其与以下内容进行比较:
//the following is good practice, try to do the following!
adapter.submitList(listOf(1, 2, 3))
adapter.submitList(listOf(7)) //will delete all the old items, insert 7 and will also trigger the need animations correctly.
虽然它们看起来很相似,但它们完全不同:第二个向适配器提交了一个全新的列表“reference-wise”,这将导致 ListAdapter
正确触发计算。
我的布局中有一个回收视图,首先它会被存储在本地数据库中的数据填充,然后几秒钟后它会使用服务器更新。
问题是在更新的时候,recycler view 的项目突然改变了,我怎样才能为 recycler view 设置一个平滑改变项目的动画?
我像这样通知我的回收站视图:
fun add(list: List<BestStockModel>) {
items.clear()
items.addAll(list)
notifyItemRangeChanged(0, list.size)
}
有更好的方法,您可以使用 ListAdapter
link。
使用 ListAdapter
您可以简单地提交一个新列表,适配器将计算新旧列表之间的差异,并为 new/changed/deleted 项添加需要的动画。
它可以使用您提供给它的简单回调来检测差异。 下面是一个示例,您可以将其用作参考:
class HomeMoviesAdapter : ListAdapter<Movie, MoviesViewHolder>(
//note the following callbacks, ListAdapter uses them
// in order to find diff between the old and new items.
object : DiffUtil.ItemCallback<Movie>() {
override fun areItemsTheSame(oldItem: Movie, newItem: Movie): Boolean =
oldItem.title == newItem.title //this can be a unique ID for the item
override fun areContentsTheSame(oldItem: Movie, newItem: Movie): Boolean =
oldItem == newItem
}
) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MoviesViewHolder {
val v: View = LayoutInflater.from(parent.context)
.inflate(R.layout.movies_item_view, parent, false)
return MoviesViewHolder(v)
}
override fun onBindViewHolder(holder: MoviesViewHolder, position: Int) {
//your binding logic goes here as usual.
}
}
然后从您拥有列表的地方(例如:片段),您可以执行以下操作:
adapter.submit(newList)
这就是列表适配器为您制作所需动画的全部内容。
不过有一个问题:如果提交相同的列表引用,适配器会认为它与旧列表相同,这意味着它不会触发差异计算。请注意以下示例:
//the following is a bad practice DO NOT do this!
val list: MutableList<Int> = mutableListOf(1, 2, 3)
adapter.submitList(list)
list.clear()
list.add(7)
adapter.submitList(list) //nothing will happen, since it's the same ref
将其与以下内容进行比较:
//the following is good practice, try to do the following!
adapter.submitList(listOf(1, 2, 3))
adapter.submitList(listOf(7)) //will delete all the old items, insert 7 and will also trigger the need animations correctly.
虽然它们看起来很相似,但它们完全不同:第二个向适配器提交了一个全新的列表“reference-wise”,这将导致 ListAdapter
正确触发计算。