Подтвердить что ты не робот

RecyclerView: как очистить кэшированные/переработанные виды?

Я использую RecyclerView для отображения списка элементов с макетом списка. Я переключаюсь с макета списка на макет сетки, показывая только подмножество всех данных, когда в макете сетки. Этот коммутатор использует другой формат XML, чем когда представлен макет списка.

Все это хорошо работает, за исключением того, что когда я просматриваю, просмотры макетов переработанных (кэшированных?) элементов заполняют сетку, смешанную с соответствующими элементами представления сетки. Другими словами, вместо использования моего layout_grid.xml для каждого макета элемента в RecyclerView я получаю элементы с использованием макета layout_list.xml, но в формате сетки.

Это говорит мне, что LayoutManager работает правильно, переключение из списка в макет сетки. Но не все элементы представления элементов воссозданы с использованием макета xml grid, но используются просмотры макетов переработанного списка.

Я пробовал RecyclerView.removeAllViews(), RecyclerView.removeAllViewInLayout(), RecyclerView.swapAdapter() (чтобы перезагрузить адаптер), все безрезультатно.

Update:

Если я прокручу две позиции вниз в списке и затем перейду из списка в сетку, первые две позиции не пройдут через onCreateViewHolder(), а прямо на onBindViewHolder() и поэтому не будут вынуждены использовать сетку xml, Вместо этого эти первые две позиции позиции перерабатываются (я думаю) и отображаются в их формате макета списка.

4b9b3361

Ответ 1

Хорошо, теперь я понимаю. Вы используете оба макета? Существует метод возврата вида вида для элемента списка/сетки (id/position). Вы тоже правильно реализуете этот метод, чтобы адаптер мог переработать правильный макет для нового представления. Вы понимаете, что я имею в виду?:)

Ответ 2

Использование

recyclerView.getRecycledViewPool().clear();

Ответ 3

У меня была та же проблема. Решение, предложенное Манном, хорошо работает. Другой вариант - установить RecycledViewPool из RecyclerView в новый экземпляр. Это работает и для меня.

recyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());

Но я считаю, что переопределение метода getItemViewType() является более чистым.

Ответ 4

Они должны были переопределить getItemViewType(int position) и настроить его таким образом, чтобы я мог проверить, какой вид (список или сетка), с которым я работаю для этой позиции, и затем установить соответствующую обработку представления для этой позиции в onbindViewHolder(). Ниже viewFormat - это просто int, который я устанавливаю в список или сетку, когда пользователь нажимает кнопку меню, чтобы изменить формат.

@Override
    public int getItemViewType(int position) {
        if (listData.size() == 0) {
            return EMPTY_VIEW;
        } else if (viewFormat == Constants.LIST_FORMATTED) {
            return Constants.LIST_FORMATTED;
        } else if (viewFormat == Constants.GRID_CONDITION) {
            return Constants.GRID_CONDITION;
        }
        return super.getItemViewType(position);
    }

Пользователь, который разместил комментарии к моему оригинальному сообщению, дал мне знать об этом, но, к сожалению, эти комментарии были отредактированы. Я благодарю этого пользователя за то, что он указал мне в правильном направлении.

Ответ 5

Похоже, что принятый ответ является правильным для вашего случая, а другой тип viewType - это то, что вам нужно было сделать.

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

Вам нужно позвонить setLayoutManager(null) и setAdapter(null). Если вы хотите сохранить свой адаптер, вы можете сделать что-то вроде adapter = getAdapter(); setAdapter(null); setAdapter(adapter);

Ответ 6

Recyclerview имеет кеширование представлений, а также пул переработанных видов (пул владельцев имен).

Кэш - это представления (представления с заполненными данными). Когда LayoutManager сообщает recyclerview, что представление больше не видимо и необходимо, recyclerview проверяет, сохраняется ли это представление для определенной позиции, если оно действительное, то оно добавляется в кеш, поэтому, когда в следующий раз LM запрашивает представление для этой позиции, он возвращает из кеша, как есть.

Тогда что такое переработанный пул представлений? Когда представления удаляются из кеша или не являются более допустимыми представлениями, данные, относящиеся к этим представлениям, очищаются, и только просмотр объекта-хранителя сохраняется в пуле. В зависимости от itemType, пул может иметь держатели для просмотра разных типов элементов.

Теперь, в вашем случае, ваши представления недействительны для этой конкретной позиции, поскольку вы хотите показать совсем другое представление. Итак, ваш адаптер должен сказать recyclerview, что все представления недопустимы. Единственный способ сделать это - использовать notifyDataSetChanged для всех элементов. Recyclerview удалит представления из кеша и добавит их в пул ресайнеров. Итак, теперь, когда LM запрашивает представление, будет возвращено либо переработанное представление (в соответствии с itemType), либо вновь созданное представление, и адаптер привяжет данные к этим представлениям.

Ответ 7

Просто сделай это Простой!!

adapter.notifyItemRangeRemoved(0,adapter.getItemCount());

  adapter.notifyItemRangeRemoved(0,adapter.getItemCount());
                   for (int i = 0; i < array.length(); i++) {
                        JSONObject object = array.getJSONObject(i);
                         ////
                        data_List.add(data);
                    }