Динамическое добавление представлений в RecyclerView только к текущему элементу

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

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

как бы одна попытка решить эту проблему?

8 ответов


как указано в обоих моих комментариях к ответ и @CQMкомментарий ниже моего первоначального вопроса, ответ должен переопределить onViewRecycled() метод и выполнять любые необходимые операции там. Этот метод вызывается при рециркуляции представления, и здесь можно выполнить любые операции очистки.

документация на этот метод можно найти здесь.

в моем случае речь шла об удалении невидимого TextViewприкреплен к представлению. Сам текст был исключен, но мнение остается. Если много невидимых TextViewнакапливаются в представлении и не перерабатываются должным образом при прокрутке, прокрутка начнет отставать.


вам нужно отслеживать, какие представления были добавлены на основе резервных данных. Я бы, вероятно, добавил любые необходимые дополнительные представления в onBindViewHolder(), и удалите все, что может присутствовать в onViewRecycled(). Затем, когда вы хотите сделать его динамически, измените любую переменную, которую вы отслеживаете, должна ли она быть видимой, и вызовите notifyItemChanged().


вы можете использовать это! setItemViewCacheSize(int size) Проверьте здесь RecyclerViewDocumentation.

кэш внешнего вида сохраняет информацию об изменениях в подключенном адаптере, позволяя LayoutManager повторно использовать эти представления без необходимости возврата к адаптеру для их повторной привязки.


исходя из этого:

но эти ранее добавленные представления все еще существуют, но теперь на неправильном элементе.

в основном, согласно RecyclerView документация, вы должны сбросить представления каждый раз внутри onBindViewHolder() метод

Итак, допустим, у вас есть метод, который устанавливает посмотреть в param если это ваш профиль, так Код же идет следующим образом:

if (list.get(position).getId()==PreferenceManager.getUserID())
{
  // do some view change here
setViewParam(true);
}else
{
  // reset the view change here
setViewParam(false);
}

Итак, что вы здесь делаете давая переработанный ViewHolder шанс сбросить. Прокомментируйте, если вам нужна помощь!


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

...
SharedPreference  sharedPref = getSharedPreference("text" + position, context);
SharedPreference.Editor editor = sharedPref.edit();
editor.putString("view", "ImageView");
...

когда адаптер нагрузки получает это значение и ставит значение по умолчанию как null. Я не уверен в его эффективности, но я буду работать.

...
String viewType = sharedPref.getString("view", null);
//it will return ImageView 

Если вы знаете некоторые возможные viewTypes, например, всегда будет ImageView & TextView так с некоторыми, если оператор будет ладно.

if(viewType.equals("ImageVIew")){
item(position).addView(new ImageVIew(context));
}

Удачи


прежде всего, вы можете поделиться еще немного кода, пожалуйста?

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

позвольте мне напомнить вам кое - что о RecyclerView, да, когда пользователь прокручивает viewHolder повторно используется (некоторые из них могут быть созданы, даже больше, чем это необходимо заполнить экран). Поэтому, если вы добавили некоторые представления на " элемент A "и прокрутите пользователя до" элемент Z", Этот держатель представления может быть повторно использован для этого" элемента Z", следовательно, отображение ранее добавленных представлений.

Как вы можете это решить?

Ну всегда проверяйте все элементы, если вам нужно добавить новые представления, если да, добавьте их, если они еще не добавлены, иначе всегда удаляйте эти представления( если они есть), чтобы вернуться в состояние viewHolder по умолчанию (или что вы называете он.)

надеюсь, это поможет вам.


в вашем классе адаптера вашего recyclerView, в onBindViewHolder способ, создайте другой адаптер и выполните те же методы для нового адаптера.

иерархия будет,

mainRecyclerView - > item1 (- >childRecyclerView1) , item2 (- >childRecyclerView2), item3 (- >childRecyclerView3)

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


вы должны взять любой пустой макет, как Linearlayout в вашем дочернем макете элемента XML а затем добавьте представления в это LinearLayout вашего конкретного элемента таким образом, когда вы прокручиваете Список всех дочерних представлений, которые вы добавили в LinearLayout также прокрутите этот элемент .