RecyclerView: как очистить кэшированные/переработанные представления?
Я использую RecyclerView для отображения списка элементов с макетом списка. Я переключаюсь с макета списка на макет сетки, показывая только подмножество всех данных в макете сетки. Этот параметр использует другой XML-файл макета, чем при представлении макета списка.
все это работает хорошо, за исключением того, что когда я прокрутки, вторичная (кэшироваться?) виды компоновки списка заполняют сетку, смешанную с соответствующими элементами компоновки сетки. Другими словами, вместо использования my layout_grid.xml
для компоновки каждого элемента в RecyclerView я получаю элементы, используя layout_list.xml
макет, но в формате сетки.
Это говорит мне, что LayoutManager работает правильно, переключаясь из списка в макет сетки. Но не все элементы представления элементов воссоздаются с помощью XML-макета сетки, а используются переработанные представления макета списка.
пробовал RecyclerView.removeAllViews()
, RecyclerView.removeAllViewInLayout()
, RecyclerView.swapAdapter()
(для принудительной перезагрузки адаптера), все безрезультатно.
обновление:
если я прокручиваю две позиции вниз в списке, а затем переключиться из списка в сетку, первые две позиции не проходят через onCreateViewHolder (), а прямо в onBindViewHolder () и поэтому не вынуждены использовать xml-макет сетки. Вместо этого эти первые два элемента позиции перерабатываются (я думаю) и отображаются в формате макета списка.
7 ответов
Ок, теперь я понимаю. Вы используете оба варианта? Существует метод для возврата viewtype для элемента списка / сетки (id/position). Вы также правильно реализуете этот метод, чтобы адаптер мог повторно использовать правильный макет для нового представления. Вы понимаете, что я имею в виду? :)
У меня была та же проблема. Решение, предложенное Манном, работает хорошо. Другой вариант - установить RecycledViewPool RecyclerView в новый экземпляр. Меня это тоже устраивает.
recyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
но я думаю, что переопределение getItemViewType () является более чистым решением.
похоже, что принятый ответ является правильным для вашего случая, возвращение другого viewType, вероятно, то, что вам нужно было сделать.
Если кому-то нужно найти способ очистить кэшированные держатели представлений и оказаться в этом потоке, вот что я нашел, что сработало.
нужно позвонить setLayoutManager(null)
и setAdapter(null)
. Если вы хотите сохранить свой адаптер, вы можете сделать что-то вроде adapter = getAdapter(); setAdapter(null); setAdapter(adapter);
они ключ здесь должен был переопределить 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);
}
пользователь, который разместил комментарии к моему исходному сообщению, сообщил мне об этом, но, к сожалению, эти комментарии были отредактированы. Я поблагодарите этого пользователя за то, что указал мне в правильном направлении.
Recyclerview имеет кэширование представления, а также пул переработанных представлений (пул держателей представлений).
кэш-это представления (представления с заполненными данными). Когда LayoutManager выполняет рассказывает recyclerview, что вид уже не видно и нужно, recyclerview проверки, если это мнение остается в силе для конкретной позиции, если это допустимо, то он добавляется в кэш, так что когда в следующий раз ЛМ просит посмотреть на эту позицию он возвращается из кэша, как это.
тогда что такое бассейн переработанных представлений? Когда представления удаляются из кэша или больше не являются допустимыми представлениями, затем данные, связанные с этими представлениями, очищаются и в пуле сохраняется только объект держателя представления. В зависимости от типа itemType пул может иметь держатели представлений различных типов элементов.
теперь, в вашем случае, ваши взгляды недействительны для этой конкретной позиции, поскольку вы хотите показать совершенно другое представление. Таким образом, ваш адаптер должен сообщить recyclerview, что все представления недействительны. Единственный способ сделать это-использовать notifyDataSetChanged для всех элементов. Recyclerview удалит представления из кэша и добавит их в пул представлений recyler. Поэтому теперь, когда LM запрашивает представление, будет возвращено либо переработанное представление(в соответствии с itemType), либо вновь созданное представление, и адаптер свяжет данные с этими представлениями.
просто сделать это Просто !!
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);
}