RecyclerView Adapter notifyDataSetChanged stops fancy animation

No, it is wrong. First of all, you cannot reference to the position passed to the onBindViewHolder after that method returns. RecyclerView will not rebind a view when its position changes (due to items moving etc).

Instead, you can use ViewHolder#getPosition() which will return you the updated position.

If you fix that, your move code should work & provide nice animations.

Calling notifyDataSetChanged will prevent predictive animations so avoid it as long as you can. See documentation for details.

Edit (from comment): to get position from the outside, get child view holder from recyclerview and then get position from the vh. See RecyclerView api for details


1) You'll use notifyItemInserted(position); or notifyItemRemoved(position); instead of notifyDataSetChanged() for animation. 2) You can just manually fix your problem - using

public void move(int from, int to){
    Track track = mArray.remove(from);
    mArray.add(to, track);
    notifyItemMoved(from, to);
    ViewHolder fromHolder = (ViewHolder) mRecyclerView.findViewHolderForPosition(from);
    ViewHolder toHolder = (ViewHolder) mRecyclerView.findViewHolderForPosition(to);
    Tag fromTag = fromHolder.itemView.getTag();
    fromHolder.itemView.setTag(toHolder.itemView.getTag()); 
    toHolder.itemView.setTag(fromTag);

}

There is a way to preserve fancy animations with just notifyDataSetChanged()

  1. You need to make your own GridLayoutManager with overriden supportsPredictiveItemAnimations() method returning true;

  2. You need to mAdapter.setHasStableIds(true)

  3. The part I find tricky is you need to override you adapter's getItemId() method. It should return value that is truly unique and not a direct function of position. Something like mItems.get(position).hashCode()

Worked perfectly fine in my case - beautiful animations for adding, removing and moving items only using notifyDataSetChanged()