RecyclerView / DiffUtils animation when dataset change without full refresh

↘锁芯ラ 提交于 2020-04-10 05:23:34

问题


I would like two things :

  • To not reload / refresh the adapter when i delete an item inside RecyclerView (no use of notifyDatasetChanged).
  • To do so i am using DiffUtils which works perfectly fine. But i also would like to keep the DefaultItemAnimator of the RecyclerView which has apparently no effect with DiffUtils.

So my question is : How can i remove / update an item without refreshing all the dataset AND keep a similar animation to the DefaultItemAnimator ?

I know many posts gives answers about the RecyclerViewbut none of them fit my needs. I am aware of the notifyItemRemoved, notifyItemRangeChanged but they also refresh all the dataset.

Thanks

EDIT giving some code for a better understanding:

In my adapter i have made two methods : This is how i remove my view at the specific position.

// Adapter methods
void removeAt(int position) {
     dataList.remove(position);
     recyclerView.removeViewAt(position);
     updateList(dataList);
     }

void updateList(ArrayList<MyModel> newList) {
     DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtilsTheme(oldList, newList));
     diffResult.dispatchUpdatesTo(this);
     }

And here is my DiffUtils class :

public class DiffUtils extends DiffUtil.Callback{

    ArrayList<MyModel> oldItems;
    ArrayList<MyModel> newItems;

    public DiffUtils(ArrayList<MyModel> newItems, ArrayList<MyModel> oldItems) {
        this.newItems = newItems;
        this.oldItems = oldItems;
    }

    /**
     *  It returns the size of the old list.
     * @return
     */
    @Override
    public int getOldListSize() {
        return oldItems.size();
    }

    /**
     * Returns the size of the new list;
     * @return
     */
    @Override
    public int getNewListSize() {
        return newItems.size();
    }

    /**
     * Called by the DiffUtil to decide whether two object represent the same Item.
     * Here we check the names because we know they are unique.
     * @param oldItemPosition
     * @param newItemPosition
     * @return
     */
    @Override
    public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
        // We are sure that the names are unique
        return oldItems.get(oldItemPosition).getItemName().equals(newItem.get(newItemPosition).getItemName());
    }

    /**
     * Checks whether two items have the same data.
     * This method is called by DiffUtil only if areItemsTheSame returns true.
     * @param oldItemPosition
     * @param newItemPosition
     * @return
     */
    @Override
    public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
        return oldItems.get(oldItemPosition).equals(newItems.get(newItemPosition));
    }

    /**
     * If areItemTheSame return true and areContentsTheSame returns false DiffUtil calls this method to get a payload about the change.
     * @param oldItemPosition
     * @param newItemPosition
     * @return
     */
    @Nullable
    @Override
    public Object getChangePayload(int oldItemPosition, int newItemPosition) {

        return super.getChangePayload(oldItemPosition, newItemPosition);
    }
}

This removes perfectly the item from the list but without animation. My RecyclerView has also the ItemAnimator :

recyclerView.setItemAnimator(new DefaultItemAnimator());

Before using the DiffUtils class, i was removing like this :

void removeAt(int position) {
     dataList.remove(position);
     notifyItemRemoved(position);
     notifyItemRangeChanged(position, dataList.size());
     }

Which was also working and with an animation, but was refreshing all the other items.

来源:https://stackoverflow.com/questions/60905423/recyclerview-diffutils-animation-when-dataset-change-without-full-refresh

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!