我有一个由SortedList支持的RecyclerView适配器。如果我对某个项目进行了更改,它将更改该项目并将其重新定位到列表中。
我发现,如果我在项目的起始位置或结束位置使用notifyItemChanged
,那么即使与notifyItemMoved
一起使用也不会产生任何影响,无论是在之前还是之后。
如果我使用notifyItemMoved
,它会正确触发移动动画,但视图不会更改,仍会显示过时的信息。
如果我使用notifyDatasetChanged
它更新行然后移动它,但它按顺序这样做很慢,它显然通知整个列表,这是不完全合乎需要的。
有什么方法可以结合移动和更新动画吗?为什么notifyItemChanged
什么都不做?
在RecyclerView.Adapter reference说,notifyItemMoved()
只是结构变化,因此不会更新数据。另一方面,据说notifyItemChanged()
是数据变化。
当调用notifyItemChanged()
时,它会调用RecyclerView#onBindViewHolder()
,因此它应该更新你的视图。
我更新和移动的工作方法是:
notifyItemChanged(oldPos); notifyItemMoved(oldPos, newPos);
看看DiffUtil https://developer.android.com/reference/android/support/v7/util/DiffUtil.html
在适配器中更新数据集后,可以使用此工具计算正确表示新数据集所需的通知。
DiffUtil.Callback
并实现Abstract方法(我创建一个看起来像这样的构造函数:
public MyDiffCallback(ArrayList<String> oldList, ArrayList<String> newList) {
this.oldList = oldList;
this.newList = newList;
}
我在内存中持有oldList
和newList
,以便我可以实现:
areItemsTheSame
areContentsTheSame
getNewListSize
getOldListSize
例如:
@Override
public int getOldListSize() {
return oldList.size();
}
@Override
public int getNewListSize() {
return newList.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).equals(newList(newItemPosition))
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return areItemsTheSame(oldItemPosition, newItemPosition);
}
areItemsTheSame
:告诉UTIL项目是否已移动(检查位置)areContentsTheSame
:通知UTIL项目内容是否已更改。
现在你在updateDataSet方法中(或者你所谓的任何方法!);做类似的事情:
public updateDataSet(List newDataSet) {
// this.dataSet is the old data set / List
final MyDiffCallback callback = new MyDiffCallback(this.dataSet, newDataSet);
final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(callback);
this.dataSet = newDataSet;
diffResult.dispatchUpdatesTo(this); //This is the Adapter
}
希望这有帮助,加夫
参考:https://medium.com/@iammert/using-diffutil-in-android-recyclerview-bdca8e4fbb00#.yhxirkkq6
您可以使用:
SortedList.updateItemAt(int position, Objet newItem)
newItem
是更新的项目,position
是当前位置。此方法替换newItem
的当前项目并将其重新定位在列表上(以及它的recyclerview链接)。
Here是官方文件。
我希望这可以帮助你。