I'm having a problem with using the notifyItemMoved()
method. It seems to be incorrectly displaying unmoved views.
My list has 4 element in it. What I want to do is animate a swap between item 1 and item 3. Items 1 and 3 swap correctly, but item 2 displays what was at item 3!
So the list starts off looking something like this:
Item 0
Item 1
Item 2
Item 3
And ends like this:
Item 0
Item 3
Item 3 <-- What the heck has this changed for?
Item 1
My adapter is backed by a List mProductList
. I call the following code:
public void sortBackingListUsingSortingList(List<ProductWrapper> newProductItems) {
Log.e("", "Before:");
for(ProductWrapper wrapper : mProductItems) wrapper.log();
for(int i = 0; i < newProductItems.size(); i++) {
ProductWrapper currentItem = mProductItems.get(i);
ProductWrapper correctItem = newProductItems.get(i);
if(!currentItem.equals(correctItem)) {
// Item in wrong place
int indexOfCorrectItem = getIndexOfItemInList(mProductItems, correctItem);
Collections.swap(mProductItems, i, indexOfCorrectItem);
notifyItemMoved(i, indexOfCorrectItem);
Log.e("", "notifyItemMoved(" + i + ", " + indexOfCorrectItem+")");
Log.e("", "After:");
for(ProductWrapper wrapper : mProductItems) wrapper.log();
}
}
}
I've also added logging to onBindViewHolder
to check if my view logic is being called:
@Override
public void onBindViewHolder(HolderBasic holder, int position) {
Log.e("", "onBindViewHolder(holder, " + position + ")");
holder.fill(mProductItems.get(position));
}
My logs look like this:
09-02 14:39:17.853: Before:
09-02 14:39:17.853: Item 0
09-02 14:39:17.853: Item 1
09-02 14:39:17.853: Item 2
09-02 14:39:17.853: Item 3
09-02 14:39:17.854: notifyItemMoved(1, 3)
09-02 14:39:17.854: After:
09-02 14:39:17.854: Item 0
09-02 14:39:17.854: Item 3
09-02 14:39:17.854: Item 2
09-02 14:39:17.854: Item 1
09-02 14:39:17.867: onBindViewHolder(holder, 1)
09-02 14:39:17.874: onBindViewHolder(holder, 3)
As you can see, no reason for Item 2 to have change it's display at all - and yet, it does. Anybody know why?
EDIT
I can get around above by looping through the entire adapter and calling notifyItemChanged()
on every item. Inefficient and not a good solution, but is invisible to the user.
See Question&Answers more detail:
os