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

У меня есть 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
  }
}

Спасибо!

Джон


person John    schedule 13.04.2019    source источник


Ответы (1)


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

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

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

override fun areContentsTheSame(oldItem: Page, newItem: Page): Boolean {
return oldItem.id == newItem.id && oldItem.image == newItem.image // If you want just add more validations here
}
person Daniel Beleza    schedule 13.04.2019
comment
Я попытался добавить поле метки времени lastUpdated к данным и изменил areContentsTheSame разницу на чтение return oldItem.id == newItem.id && oldItem.lastUpdated == newItem.lastUpdated, но, похоже, это все еще не вызывает обновление onBindViewHolder, где я ожидаю увидеть действие. Вместо того, чтобы использовать notifyDataSetChanged(), я использую submitList(), который запускает обратный вызов Different, но, что интересно, метка времени для oldItem такая же, как и метка времени для newItem, что может быть причиной того, что представление не перезапускается, а onBindViewHolder не вызывается. - person John; 14.04.2019