RecyclerView - 如何同时更新和移动项目

时间:2017-03-05 23:59:06

标签: android android-recyclerview sortedlist

我有一个由SortedList支持的RecyclerView适配器。如果我对某个项目进行了更改,它会更改该项目并将其重新定位到列表中。

我发现如果我在项目的起始位置或结束位置使用notifyItemChanged,那么即使与notifyItemMoved一起使用,也不会在之前或之后产生任何影响。

如果我使用notifyItemMoved,它会正确触发移动动画,但视图不会更改,仍会显示过时的信息。

如果我使用notifyDatasetChanged它会更新行然后移动它,但它按顺序执行,这很慢,并且它显然会通知整个列表,这不是完全合乎需要的。

有什么方法可以结合移动和更新动画吗?为什么notifyItemChanged没有做任何事情?

3 个答案:

答案 0 :(得分:4)

RecyclerView.Adapter reference中,notifyItemMoved()只是结构变化,因此不会更新数据。另一方面,据说notifyItemChanged()是数据更改。

致电notifyItemChanged()时,会致电RecyclerView#onBindViewHolder(),因此应该更新您的观点。

我更新和移动的工作方法是:

notifyItemChanged(oldPos); notifyItemMoved(oldPos, newPos);

答案 1 :(得分:0)

看看DiffUtil https://developer.android.com/reference/android/support/v7/util/DiffUtil.html

在适配器中更新数据集后,您可以使用此工具计算正确表示新数据集所需的通知。

  1. 扩展DiffUtil.Callback并实现抽象方法(我创建一个看起来像这样的构造函数:

    public MyDiffCallback(ArrayList<String> oldList, ArrayList<String> newList) {
    
        this.oldList = oldList;
        this.newList = newList;
    }
    
  2. 我在内存中保留oldListnewList,以便我可以实现:

    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
    }
    

    希望这有帮助, GAV

    参考:https://medium.com/@iammert/using-diffutil-in-android-recyclerview-bdca8e4fbb00#.yhxirkkq6

答案 2 :(得分:0)

您可以使用:

SortedList.updateItemAt(int position, Objet newItem)

newItem是更新的项目,position是当前位置。此方法替换newItem的当前项,并将其重新定位在列表中(以及它的recyclerview链接)。

Here是官方文档。

我希望这会对你有所帮助。