RecyclerView corrupts view using notifyItemMoved()

I had the same issue. RecyclerView-Items are corrupt on drag&drop. But I have found a simple solution: In your RecyclerView.Adapter.class be sure to have the following

@Override
public long getItemId(int position) {
    // here code for getting the right itemID, 
    // i.e. return super.getItemId(mPosition);
    // where mPosition ist the Position in the Collection.
}

You must return the right itemID for the position. From now on the Items are not corrupt.


Thank you to @david.mihola for leading me to what I'm doing wrong.

This took so long to figure out as the symptom didn't make the problem obvious!

I was doing this:

Collections.swap(mProductItems, i, indexOfCorrectItem);
notifyItemMoved(i, indexOfCorrectItem)

But, I obviously didn't think through what notifyItemMoved() was actually doing. It is only notifying the adapter that item i has moved to indexOfCorrectItem it isn't telling the adapter that indexOfCorrectItem has also moved to i.

Under the covers it was doing the following:

  1. Move item 1 to 3
  2. Move what was at 2 to 1 to fill the gap
  3. Move what was at 3 to 2 to fill the gap
  4. notifyItemChanged(1);
  5. notifyItemChanged(3);

The above of course leaves item 3 moved down to item 2 without a refreshed view! It was steps 4 and 5 which were hiding the problem by making item1 and item3 display correctly and leaving item2 incorrect!

As soon as I realised this I tried the following code:

notifyItemMoved(indexOfCorrectItem, i);
notifyItemMoved(i, indexOfCorrectItem);

This left the list in the correct order, but it short circuited the animation.

So, instead, I dumped swapping altogether:

mProductItems.remove(indexOfCorrectItem);
mProductItems.add(i, correctItem);
notifyItemMoved(indexOfCorrectItem, i);