Ошибка изображения элемента 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() если вы вызываете его непосредственно из класса адаптера.

Intereting Posts
Отменить возвращаемое значение для возврата Unit? TornadoFX обертывает классы домена в ItemViewModel Regex – слова соответствия, которые не являются строками Как высмеять функцию верхнего уровня в котлине с помощью jmockit Nullability и LiveData с Kotlin Не удалось выполнить синхронизацию проекта Gradle, Котлин версия kotlin, которая используется для построения с градиентом (1.1.2-5), отличается от той, что включена в плагин IDE (1.1.2-4) Как создать обещание из вложенного kotlin.js.Promise? Как правильно обращаться с ошибками при использовании HTTP-клиента в Котлине? Kotlin webview crash Использование функции чтения AudioRecord в Kotlin не соответствует аргументам типов платформ Конструкторы по умолчанию Kotlin Как запустить тесты, компилирующие файл kotlin в память и проверить результат? tornadofx EventBus развернуть таблицу с использованием объекта tableview Firebase неразрешенный супертип с Kotlin на Android