Ошибка изображения элемента RecyclerView

Проблема: ошибка с ошибкой с дочерним элементом RecyclerView ImageView

У меня есть RecyclerView. Каждый элемент имеет ImageView с id «like», который в основном пустой звездой.

Когда мы нажимаем на «Похоже» на каком-то элементе, например, первый, звезда меняется с пустого, заполненного желтым, что означает, что этот предмет понравился.

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

Если мы щелкнем по второму элементу – седьмой элемент будет иметь такую ​​же ошибку.

Чтобы заполнить элемент в ViewHolder, у меня есть модель – Рецепт.

open class Recipe constructor(open var label: String, open var image: String, open var url: String, open var ingredients: RealmList<Ingredient>?, open var calories: Float, open var totalWeight: Float, open var id: Int, open var isFavorite: Boolean) : RealmObject() 

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

У кого-нибудь есть идеи, как я должен это исправить?

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

Прослушиватель OnClick для кнопки «like»

 itemView.like.onClick { if (recipe.isFavorite) { itemView.like.image = ContextCompat.getDrawable(itemView.context, R.drawable.ic_star_before_like) recipe.isFavorite = false DatabaseService.removeRecipeFromFavorites(recipe) itemView.context.toast("Recipe removed from favorites.") } else { itemView.like.image = ContextCompat.getDrawable(itemView.context, R.drawable.ic_star_after_like) recipe.isFavorite = true DatabaseService.addNewFavoriteRecipe(recipe) itemView.context.toast("Recipe added to favorites.") } } 

XML-файл

 <LinearLayout android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="0.8" android:gravity="center|right" android:orientation="horizontal"> <ImageView android:id="@+id/like" android:layout_width="@dimen/icon_size_card" android:layout_height="@dimen/icon_size_card" android:padding="5dp" android:layout_marginRight="@dimen/icon_margin_card" android:src="@drawable/ic_star_before_like" /> <ImageView android:id="@+id/share" android:layout_width="@dimen/icon_size_card" android:layout_height="@dimen/icon_size_card" android:padding="5dp" android:layout_marginRight="@dimen/icon_margin_card" android:src="@drawable/ic_share" /> <ImageView android:id="@+id/save" android:layout_width="@dimen/icon_size_card" android:layout_height="@dimen/icon_size_card" android:padding="5dp" android:layout_marginRight="@dimen/icon_margin_card" android:src="@drawable/ic_save_recipe" /> <ImageView android:id="@+id/expand" android:layout_width="@dimen/icon_size_card" android:layout_height="@dimen/icon_size_card" android:padding="5dp" android:layout_marginRight="@dimen/icon_margin_card" android:src="@drawable/ic_down_arrow" /> </LinearLayout> 

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

  1. Установите значок в нужное место в методе onBindViewHolder . Таким образом, независимо от того, привязан ли зритель в первый раз или был ли он доступен, отражая состояние, полученное от рецепта, он будет обновлен должным образом.

    Не зная, как выглядит ваш адаптер, это должно дать вам представление о том, как это сделать (пример кода предполагает, что у вас есть рецепты в некотором списке, называемом recipes ):

     override fun onBindViewHolder(holder: ViewHolder, position: Int) { val recipe = recipes[position] val itemView = holder.itemView itemView.like.image = ContextCompat.getDrawable(itemView.context, if(recipe.isFavorite) R.drawable.ic_star_before_like else R.drawable.ic_star_after_like) } 
  2. В слушателе измените Recipe же, как вы это делаете сейчас, но вместо того, чтобы затем напрямую установить изображение, сообщите об этом адаптеру, который изменил рецепт в данной позиции ( notifyItemChanged(position) ), что сделает его повторно – привяжите этот элемент, обновив значок, чтобы отразить новое состояние. Опять же, я не знаю, где вы настраиваете слушателя, но я предполагаю, что вы знаете, в какой позиции находится рецепт в списке.

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

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