Android Recyclerview适配器和Glide-每4-5行显示一个相同的图像

Android Recyclerview适配器和Glide-每4-5行显示一个相同的图像,android,parse-platform,android-recyclerview,android-glide,Android,Parse Platform,Android Recyclerview,Android Glide,我有这个问题-为了测试,我从接收列表中将ParseFile添加到ParseObject之一。它不是仅在该行中显示,而是每4-5行显示一次,有时更多,有时更少。我怀疑回收观点与此有关。奇怪的是,其他数据(从本例中删除)可以与position变量配合使用 @Override public void onBindViewHolder(ViewHolder holder, int position) { if(parseList.get(position).get("logo")

我有这个问题-为了测试,我从接收列表中将
ParseFile
添加到
ParseObject
之一。它不是仅在该行中显示,而是每4-5行显示一次,有时更多,有时更少。我怀疑回收观点与此有关。奇怪的是,其他数据(从本例中删除)可以与
position
变量配合使用

@Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        if(parseList.get(position).get("logo") != null){
            ParseFile image = (ParseFile) parseList.get(position).get("logo");
            String url = image.getUrl();
            Glide.with(context)
                    .load(url)
                    .placeholder(R.drawable.piwo_48)
                    .transform(new CircleTransform(context))
                    .into(holder.imageView);


        }

    }
当“logo”为空时,您将获得回收的图像,而不是清除它。添加以下代码以正确清除图像:

holder.imageView.setImageDrawable(null);

RecyclerView
中,每一行都使用新数据进行回收。在代码中,仅当图像视图不为空时,才设置图像视图,否则不执行任何操作。在这种情况下,当它不为null时,
ImageView
将显示旧图像,因为您没有为当前对象覆盖
。您可以通过添加else条件并将
ImageView
设置为null/blank anything来修复此问题

@Override 
    public void onBindViewHolder(ViewHolder holder, int position) {
        if(parseList.get(position).get("logo") != null){
            ParseFile image = (ParseFile) parseList.get(position).get("logo");
            String url = image.getUrl();
            Glide.with(context) 
                    .load(url)
                    .placeholder(R.drawable.piwo_48)
                    .transform(new CircleTransform(context)) 
                    .into(holder.imageView);


        } 
        else{
            holder.imageView.setImageDrawable(null);
        }
    } 

这里的答案是不正确的,尽管他们在正确的轨道上

您需要调用
Glide#clear()
,而不仅仅是将图像drawable设置为null。如果不调用
clear()
,异步加载无序完成仍可能导致视图回收问题。您的代码应该如下所示:

@Override 
public void onBindViewHolder(ViewHolder holder, int position) {
    if (parseList.get(position).get("logo") != null) {
        ParseFile image = (ParseFile) parseList.get(position).get("logo");
        String url = image.getUrl();
        Glide.with(context) 
                .load(url)
                .placeholder(R.drawable.piwo_48)
                .transform(new CircleTransform(context)) 
                .into(holder.imageView);
    } else {
        // make sure Glide doesn't load anything into this view until told otherwise
        Glide.with(context).clear(holder.imageView);
        // remove the placeholder (optional); read comments below
        holder.imageView.setImageDrawable(null);
    }
} 

也许你需要试试这样的东西

.signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
样本:

Glide.with(context)
                .load(url)
                .placeholder(R.drawable.progress_animation)
                .crossFade()
                .signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
                .error(R.drawable.image_error_404)
                .into(iv);

我想这是因为你的适配器 adapter.SetHassTableId(true)
为true,并且未重写getItemId。因此,recyclerView尝试找到具有相同id的持有者并重新使用

我知道这是一种可以循环利用的东西,但我从未想过这样。非常感谢,它立即起作用:)这个答案不完整。您还需要在所讨论的图像视图上调用Glide.clear(),否则,当异步加载稍后完成时,您可能仍然会看到单元格重用问题。@samajudd我刚刚找到了一个-因此我应该同时调用
setImageDrawable(null)
Glide.clear()
?有趣的事情-当我实现了这两个答案并且
clear()
是第一个,我只得到一个剩余的imageview,但当调用
clear()
时,它第二个工作。萨马贾德,你就是这么做的吗?他们大部分都在工作。如果调用onBindViewHolder并开始加载具有给定视图徽标的位置,然后在加载完成之前再次使用相同的ViewHolder调用onBindViewHolder,您将看到旧图像而不是空白视图。这种竞争条件比您以前的错误要少见得多,但仍然有可能。另外,我应该澄清一下,我编写了库和clear()方法。这里的这个用例是clear()方法存在的一个很好的例子:)。在使用视图时,您必须始终启动新加载(这将为您取消旧加载)或自己取消加载。请稍候-您编写了Glide,Bumptech?:)中的Glide)如果不想显示占位符,可以在clear()调用后调用setImageDrawable(null)。clear()只是确保Glide将来不会对视图做任何事情(如果稍后异步加载完成)。可能需要使用
Glide.with(context).clear(view)