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:
- Move item 1 to 3
- Move what was at 2 to 1 to fill the gap
- Move what was at 3 to 2 to fill the gap
notifyItemChanged(1);
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);