Удаление нескольких items из RecyclerView
Всем привет! Есть RecyclerView, которым управляю через адаптер.
Несколько элементов добавляю так:
public void addItemsToList(ArrayList<Item> itemsList)
{
items.addAll(itemsList);
adapter.notifyDataSetChanged();
}
Один элемент добавляю так:
public void addCommentToList(Item item)
{
items.add(item);
adapter.notifyDataSetChanged();
}
Для списка прописана возможность множественного выбора элементов и их удаления. На клиенте пользователь выбирает элементы списка, их id отправляется на сервер и при успешном удалении из БД приход ответ.
Знаю, что удалить один элемент можно по его позиции и обновить отображение в адаптере так:
public void deleteItemFromList(int position)
{
items.remove(position);
adapter.notifyItemRemoved(position);
}
Нашёл вариант, когда удаляются несколько элементов, которые следуют друг за другом в списке (через номера позиций, например с 1 по 4), но он не подходит, потому что могут быть выбраны элементы из разных позиций, не идущие друг за другом.
Сейчас я сохраняю позиции элементов для удаления в ArrayList, а потом пытаюсь перебрать их:
public void deleteItemsFromList(ArrayList<Integer> positions)
{
for (int i = 0; i < positions.size(); i++)
{
items.remove(positions.get(i));
adapter.notifyItemRemoved(positions.get(i));
}
}
Но такой вариант работает некорректно (сначала удаляет элементы, а потом обновляет список и они снова появляются). Думаю, что должен быть какой-то универсальный способ такого удаления.
Вопрос в том, как правильно удалить сразу несколько элементов из списка и обновить его, если известны позиции для удаления?
Ответы (2 шт):
Я бы сделал это так:
Создал бы в Adapter метод вроде такого:
public void update(List<Item> items){
this.items.clear();
this.items.addAll();
notifyDataSetChanged(); //вот тут лучше использовать DiffUtils вместо этого метода
}
Весь список данных стоит держать где-то за пределами Adapter, например Presenter/ViewModel. Как только вы нажимаете "удалить N элементов" - вы передаете список этих элементов в ваш Presenter/ViewModel, там удаляете их из списка и вызываете метод update() адаптера с новыми данными.
Чтоб каждый раз не пересоздавать весь список используйте DiffUtils.
При таком подходе ваш адаптер будет уметь только отрисовывать элементы (соблюдается Принцип единой ответственности), и вы сможете легко изменять его содержимое в любом месте вашего кода.
Единственное, что вам придется решить как вы будете получать список удаляемых элементов.
Есть альтернативный способ решения проблемы.
Поскольку вы берете список из БД, то следует объявить адаптер как
hasStableIds()и вItemзавестиidравный первичному ключу БД (обычноLong) откуда вы берете данныеКогда вы помечаете элемент на удаление создаете списочек
ArrayList<Long> idsToRemove, черезadapter.getItemId(position)Далее проходитесь по списку элементов
idsToRemove, спокойно все удаляете и вызываетеnotifyDataSetChanged()