У меня возникла проблема с использованием метода notifyItemMoved()
. Кажется, это неверно отображает невозмущенные представления.RecyclerView развращает просмотр с помощью notifyItemMoved()
В моем списке 4 элемента. То, что я хочу сделать, - это оживить обмен между пунктом 1 и пунктом 3. Позиции 1 и 3 меняются правильно, но в пункте 2 отображается то, что было в пункте 3!
Так что список начинается выглядеть примерно так:
Item 0
Item 1
Item 2
Item 3
И заканчивается так:
Item 0
Item 3
Item 3 <!-- What the heck has this changed for?
Item 1
Мой адаптер подкреплена List mProductList
. Я называю следующий код:
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();
}
}
}
Я также добавил, войдя в onBindViewHolder
, чтобы проверить, если моя точка зрения логики называют:
@Override
public void onBindViewHolder(HolderBasic holder, int position) {
Log.e("", "onBindViewHolder(holder, " + position + ")");
holder.fill(mProductItems.get(position));
}
Мои журналы выглядеть следующим образом:
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)
Как вы можете видеть, нет никаких оснований для того, чтобы пункт 2 имел изменения, и это вообще отображается. Кто-нибудь знает, почему?
EDIT
я могу обойти выше, обернув через весь адаптер и вызов notifyItemChanged()
по каждому пункту. Неэффективное и нехорошее решение, но оно невидимо для пользователя.
Итак, я думаю, вы говорите, что 'onBindViewHolder (owner, 1)' не следует вызывать, правильно? Я также не знаю, почему он * называется *. Но я также думаю, что вам нужно просто называть 'notifyItemChanged (i); notifyItemChanged (indexOfCorrectItem); 'вместо' notifyItemMoved (i, indexOfCorrectItem); 'Вы пробовали это? –
Нет, проблема в том, что элемент 2 меняет свое отображение. onBindViewHolder следует вызывать для 1 и 3, потому что notifyItemMoved (1, 3) отмечает, что оба они нуждаются в перерисовании. То, что не должно происходить, должно быть затронуто во 2-м пункте, его не следует трогать. – Graeme
Я не знаю, почему RecyclerView ведет себя точно так, как он есть, но я * могу понять, что он смущен тем, что вы делаете: вы начали с '[0, 1, 2, 3]'. Вызывая 'notifyItemChanged (1, 3)' вы говорите: «Я удалил позицию позиции 1, вставленную в позицию 3». Чтобы это было верно, ваш список теперь должен быть '[0, 2, 3, 1]'. Но на самом деле это '[0, 3, 2, 1]', поэтому, если он затем вызывает 'onBindViewHolder (владелец, 1)' *, конечно *, он увидит '3' и перезапишет' 2', что был там раньше. Меня озадачивает только то, что он чувствует необходимость даже называть это ... –