Android - 使用一个布局的RecyclerView,实现多个setVisibility

4
我有一个基本的全能布局,其中包含了我的应用程序主要的信息流所需的所有内容。所有可变项(图像、视频缩略图等)最初都被设置为GONE,当需要时再设置为VISIBLE
问题是有时候,可能是由于RecyclerView的回收行为,本应该是GONE的项目在错误的位置上是VISIBLE的。
例如:
块引用:

第1个项目包含文本

第2个项目包含图像

第3个项目包含图像

我不断向下滚动到第x个项目,然后向上滚动,这就是我得到的结果:
块引用:

第1个项目包含来自第x个项目的图像,有时是第3个项目

第2个项目包含图像

第3个项目包含图像

我正在使用一个自定义的ViewHolder,它extends RecyclerView.ViewHolderCustomViewHolder的目的是进行布局声明和初始化。
    ProgressBar progressBar;
    View viewDimmer;
    RelativeLayout postListWrapper;

    ...

    public ObjectViewHolder(View v) {
        super(v);
        progressBar = (ProgressBar)v.findViewById(R.id.post_inscroll_progressBar);
        viewDimmer = (View)v.findViewById(R.id.post_inscroll_viewDimmer);
        postListWrapper = (RelativeLayout)v.findViewById(R.id.post_inscroll_postListWrapper);
    }

我加载图片的一个示例:

Picasso.with(context)
    .load(youtubeThumbnailUrl)
    .fit()
    .centerCrop()
    .into(
        ((ObjectViewHolder) holder).userPostYoutubeImage
    );

如果从服务器获取不到URL,我会将每个可见性设置为GONE
((ObjectViewHolder) holder).userPostImageWrapper.setVisibility(View.GONE);
((ObjectViewHolder) holder).userPostYoutubeImageWrapper.setVisibility(View.GONE);

但是不知怎么的,这个图片仍然被用在了之前的项目上(不仅仅是第一个项目)。有时图片也出现在错误的 ImageView 中。 图片 D 应该在 ImageView D 中,但实际上却出现在 ImageView A 中。

关于如何设置和流畅使用 RecyclerView,有什么指南吗?

如果我漏掉了什么,或需要提供更多代码,请告诉我:D

2个回答

6
你需要添加 else 条件。就像下面的例子一样。
// if no url is found from server
if(url == null){
  ((ObjectViewHolder) holder).userPostImageWrapper.setVisibility(View.GONE);
  ((ObjectViewHolder) holder).userPostYoutubeImageWrapper.setVisibility(View.GONE);

} else {
  // Some url has found 
  ((ObjectViewHolder) holder).userPostImageWrapper.setVisibility(View.VISIBLE);
  ((ObjectViewHolder) holder).userPostYoutubeImageWrapper.setVisibility(View.VISIBLE);
}

如果您在运行时设置列表项的可见性,请针对每个项目执行此操作。


3
这个很重要,值得解释一下。因为持有者会被再次使用。 - Knossos
我刚刚受到了心灵上的打击。感谢 Reaz 告诉我要使用 else,以及感谢 @Knossos 告诉我 Holder 是可以重复利用的!所以,在 Holder 数字 3 中的可见性仍然存在,即使我们移动到 Holder 数字 1? - Kevin Murvie
@KevinMurvie 正确。重复使用从RecyclerView弹出的Holder比创建新的更有效率。因此,每当您在Holder中设置属性时,它将保持该属性,以便下次使用。因此,它需要被重置为默认值。 - Knossos
好的,我目前正在添加 else 语句,以便在需要默认重置时使用。但是我的方法是否正确呢?也就是说只使用一个布局。 - Kevin Murvie
是的,你可以继续你现在正在做的事情。应该可以正常工作。 - Reaz Murshed
显示剩余2条评论

0

onBindViewHolder() 中的所有 if 条件语句都必须有一个 else 块。

不要留下任何没有else块的if条件语句。当if条件变为false时,您可以在 else 块中提供默认行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接