Как обновить изображения в RecyclerView?

#android #kotlin #android-recyclerview #android-diffutils

#Android #kotlin #android-recyclerview #android-diffutils

Вопрос:

У меня есть RecyclerView изображений, которые пользователь может редактировать непосредственно в самом RecyclerView.

Часть редактирования в порядке и работает хорошо. Это делается на растровом изображении, которое накладывается на изображения, а затем сохраняет все изменения в файле изображения. Как только пользователь прокручивает recyclerview, растровое изображение уничтожается и становится невидимым.

Проблема в том, что любые изменения, вносимые пользователем, не видны при прокрутке. Они прокручивают СТАРОЕ изображение, а не ОТРЕДАКТИРОВАННОЕ изображение. Они должны выйти из утилизатора и вернуться в него, чтобы увидеть изменения.

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

 class InfinityPageAdapter(val memo: Memo) : ListAdapter<Page, InfinityPageAdapter.ViewHolder>(PageDiffCallback()) {

  class ViewHolder(pageView: View) : RecyclerView.ViewHolder(pageView)

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): InfinityPageAdapter.ViewHolder {
    val pageView = LayoutInflater.from(parent.context).inflate(R.layout.infinity_page_list_item, parent, false)
    return ViewHolder(pageView)
  }

  override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val page = getItem(position)

    val imageUrl = getMemoPath(memo.uuid)   page.uuid   ".webp"
    if (imageUrl.isNotEmpty()) {
        Glide.with(holder.itemView.context)
                .load(imageUrl)
                .apply(RequestOptions()
                        .signature(ObjectKey(System.currentTimeMillis()))
                        .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
                        .override(memo.pageWidth,memo.pageHeight)
                )
                .transition(DrawableTransitionOptions.withCrossFade())
                .into(holder.itemView.findViewById(R.id.memo_page_image))
    }
  } 
 

Есть ли способ уведомить recyclerview о том, что изображение изменилось, и принудительно перезагрузить изображение?

Я использую DiffUtil на адаптере. Насколько я понимаю, мне не нужно использовать notifyDataSetChanged(), когда вы используете DiffUtil. Но я не понимаю, как вы уведомляете об изменении изображения.

Я не знаю, является ли проблема с обратным вызовом Diff. Для чего это стоит, вот оно. Он не просматривает сам файл изображения, только имя файла изображения. Возможно, из-за того, что имя не меняется, изображение не обновляется. Но я не хочу менять имя файла при каждом редактировании.

 class PageDiffCallback : DiffUtil.ItemCallback<Page>() {

    override fun areItemsTheSame(oldItem: Page, newItem: Page): Boolean {
    return oldItem.id == newItem.id
  }

  override fun areContentsTheSame(oldItem: Page, newItem: Page): Boolean {
    return oldItem == newItem
  }
}
 

Спасибо!

Джон

Ответ №1:

Дело в том, что вы обновляете не весь элемент в своем представлении recycler, а строку. notifyDataSetChanged() принудительно обновит данные, как вы сказали, но в этом случае он также обновит ваш макет.

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

Прежде чем пытаться использовать notifyDataSetChanged(), не могли бы вы попробовать сделать это в своем areContentsTheSame() методе:

 override fun areContentsTheSame(oldItem: Page, newItem: Page): Boolean {
return oldItem.id == newItem.id amp;amp; oldItem.image == newItem.image // If you want just add more validations here
}
 

Комментарии:

1. Я попытался добавить поле метки lastUpdated времени к данным и изменил значение areContentsTheSame difference на read return oldItem.id == newItem.id amp;amp; oldItem.lastUpdated == newItem.lastUpdated , но, похоже, оно по-прежнему не запускает обновление onBindViewHolder , в котором я ожидаю увидеть действие. Вместо того, чтобы использовать notifyDataSetChanged() I’m using submitList() , который запускает обратный вызов different , но, что интересно, временная метка в oldItem совпадает с временной меткой в newItem, что может быть причиной того, что представление не перерабатывается, а onBindViewHolder не вызывается.