使用notifyItemChanged和Glide时RecyclerView图像闪烁

时间:2019-07-23 01:40:58

标签: android android-recyclerview

我看到了一些相似但有显着差异的问题。

预期:

我有一个垂直的RecyclerView单元格,上面有图像和下方的一些按钮。使用Glide动态调整图像大小并加载图像。用户单击按钮时,它将更新数据集并在单击按钮的项目上执行notifyItemChanged。然后,应使用相同的图像平稳地重新加载单元,并进行必要的状态更改。

实际

当用户单击按钮时,单元和按钮将根据需要重新加载,但是图像从0高度恢复到全高度时,图像会明显闪烁。

我到目前为止所拥有的

据我了解,这是因为在该单元格上调用了onBindViewHolder,该单元格也通过滑行重新加载了图像(从而导致闪烁)。我添加了一个if检查,以尝试防止在相同的图像或支架作用下重新加载图像。示例:

if (holder.tag == null || !holder.tag.equals(item.getId())) {
     // Load image via Glide
}

但是,这不能正确触发。似乎当调用onBindViewHolder时,绑定到同一位置的单元格不是同一单元格,而是其他一些不活动的单元格(该单元格本身未在重用,而是正在使用另一种不活动的单元格带来替换)。

问题

  • 正在用不活动的单元格替换可见的单元格,然后为notifyItemChanged重新配置预期的重复使用行为。
  • 如果是这样,我还可以做其他事情,以便在用户交互时仅重新配置活动单元的某些部分。理想情况下,我不想完全抛弃单元格并重新绘制,否则我最终会出现相同的图像闪烁。

临时解决方法

我从db重新加载RecyclerView项,而没有通知,然后使用onClick内部对支架的引用来手动更改按钮状态。我宁愿通过简单地重新绑定整个视图来“适当地”做到这一点

任何建议将不胜感激

1 个答案:

答案 0 :(得分:1)

我已经遇到了这个问题,并通过使用毕加索找到了解决方案。毕加索为此.noPlaceholder()

提供了一个不错的方法调用

它的作用是告诉毕加索在放置新图像之前不要从视图中删除旧图像。这是导致ImageView闪烁的原因。似乎毕加索正在重新加载图像,效果不佳,但至少您的用户看不到闪烁

              Picasso.get()
                .load(itemModel().getImageUrl())
                .error(R.drawable.place_holder_image)
                .noPlaceholder()
                .into(holder.postImage);

编辑:在上述解决方案中,您将在回收视图时发现问题。毕加索主要是先显示旧图像,再显示新图像(因为视图已回收)。这是另一种解决方案。如果您知道不需要重新加载图像视图,那么不要让Picasso尝试重新加载。

 if (holder.postImage.getTag() == null || !itemModel().getImageUrl().equals((String)holder.postImage.getTag())) {
            Picasso.get()
                    .load(model.getImageUrl())
                    .error(R.drawable.place_holder_image)
                    //.noPlaceholder() --Don't use this.
                    .placeholder(R.drawable.place_holder_image)
                    .into(holder.postImage);
            holder.postImage.setTag(model.getImageUrl());
        }