TransWikia.com

Удаление нескольких items из RecyclerView

Stack Overflow на русском Asked by DenVebber on December 9, 2021

Всем привет!
Есть 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 Answers

Есть альтернативный способ решения проблемы.

  1. Поскольку вы берете список из БД, то следует объявить адаптер как hasStableIds() и в Item завести id равный первичному ключу БД (обычно Long) откуда вы берете данные

  2. Когда вы помечаете элемент на удаление создаете списочек ArrayList<Long> idsToRemove, через adapter.getItemId(position)

  3. Далее проходитесь по списку элементов idsToRemove, спокойно все удаляете и вызываете notifyDataSetChanged()

Answered by Barmaley on December 9, 2021

Я бы сделал это так:

Создал бы в Adapter метод вроде такого:

public void update(List<Item> items){
    this.items.clear();
    this.items.addAll();
    notifyDataSetChanged(); //вот тут лучше использовать DiffUtils вместо этого метода
}

Весь список данных стоит держать где-то за пределами Adapter, например Presenter/ViewModel. Как только вы нажимаете "удалить N элементов" - вы передаете список этих элементов в ваш Presenter/ViewModel, там удаляете их из списка и вызываете метод update() адаптера с новыми данными.

Чтоб каждый раз не пересоздавать весь список используйте DiffUtils.

При таком подходе ваш адаптер будет уметь только отрисовывать элементы (соблюдается Принцип единой ответственности), и вы сможете легко изменять его содержимое в любом месте вашего кода.

Единственное, что вам придется решить как вы будете получать список удаляемых элементов.

Answered by Sergei Buvaka on December 9, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP