RecyclerView适配器显示错误的图像

我有一个RecyclerView适配器,看起来像这样:

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> { private static Context context; private List<Message> mDataset; public RecyclerAdapter(Context context, List<Message> myDataset) { this.context = context; this.mDataset = myDataset; } public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener, View.OnClickListener { public TextView title; public LinearLayout placeholder; public ViewHolder(View view) { super(view); view.setOnCreateContextMenuListener(this); title = (TextView) view.findViewById(R.id.title); placeholder = (LinearLayout) view.findViewById(R.id.placeholder); } } @Override public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_layout, parent, false); ViewHolder vh = new ViewHolder((LinearLayout) view); return vh; } @Override public void onBindViewHolder(ViewHolder holder, int position) { Message item = mDataset.get(position); holder.title.setText(item.getTitle()); int numImages = item.getImages().size(); if (numImages > 0) { View test = LayoutInflater.from(holder.placeholder.getContext()).inflate(R.layout.images, holder.placeholder, false); ImageView image = (ImageView) test.findViewById(R.id.image); Glide.with(context) .load("http://img.androidcookie.com/android/test.png") .fitCenter() .into(image); holder.placeholder.addView(test); } } @Override public int getItemCount() { return mDataset.size(); } } 

但是,RecyclerView中的一些项目不应该显示图像。 我怎样才能阻止这种情况发生?

我做检查if (numImages > 0) {onBindViewHolder() ,但仍然没有停止显示图像的项目,不应该有图像。

我也有RecyclerView显示错误的图像的问题。 发生这种情况是因为RecyclerView没有为每个新的列表项目添加视图:而是正在回收列表项目。

通过回收视图,我们可以粗略理解克隆视图。 克隆的视图可能会有一个来自以前的交互的图像集。

如果您正在使用Picasso,Glide或其他lib进行asynchronous加载,这是特别公平的。 这些库保存对ImageView的引用,并在加载图像时在该引用上设置图像。

当图像被加载时,项目视图可能被克隆,图像将被设置为错误的克隆

长话短说,我通过限制RecyclerView克隆我的项目视图来解决这个问题:

在ViewHolder构造函数中使用setIsRecyclable(false)

现在RecyclerView工作起来有点慢,但至less图像设置正确。

否则cansel加载图像在onViewRecycled(ViewHolder holde)

在使用滑动设置图像之前,应该在onBindViewHolder()设置onBindViewHolder() imageView.setImageDrawable (null)

将图像绘制为null可以解决问题。

希望能帮助到你!

问题是在onBindViewHolder,在这里:

  if (numImages > 0) { View test = LayoutInflater.from(holder.placeholder.getContext()).inflate(R.layout.images, holder.placeholder, false); ImageView image = (ImageView) test.findViewById(R.id.image); Glide.with(context) .load("http://img.androidcookie.com/android/test.png") .fitCenter() .into(image); holder.placeholder.addView(test); } 

如果numImages等于0,则只需将之前启动的加载放入要重用的视图中即可。 完成后,仍然会将旧图像加载到您的视图中。 为了防止这种情况,请通过调用clear来告诉Glide取消以前的加载:

  if (numImages > 0) { View test = LayoutInflater.from(holder.placeholder.getContext()).inflate(R.layout.images, holder.placeholder, false); ImageView image = (ImageView) test.findViewById(R.id.image); Glide.with(context) .load("http://img.androidcookie.com/android/test.png") .fitCenter() .into(image); holder.placeholder.addView(test); } else { Glide.clear(image); } 

当你调用into() ,Glide会为你取消旧的加载。 如果你不into() ,你必须自己调用clear()

每次调用onBindViewHolder都必须包含load()调用或clear()调用。

这里的问题是,当您正在处理将要被回收的视图时,您需要在绑定视图时处理所有可能的场景。

例如,如果要将ImageView添加到数据源的位置0上的LinearLayout,则如果位置4不符合条件,则在绑定位置0时,其视图很可能会添加ImageView。

你可以在你的内部添加R.layout.images内容

R.layout.message_layout布局的R.id.placeholder ,根据大小写显示/隐藏占位符。

所以,你的onBindViewHolder方法就像这样:

 @Override public void onBindViewHolder(ViewHolder holder, int position) { Message item = mDataset.get(position); holder.title.setText(item.getTitle()); int numImages = item.getImages().size(); if (numImages > 0) { holder.placeholder.setVisivility(View.VISIBLE); ImageView image = (ImageView)holder.placeholder.findViewById(R.id.image); Glide.with(context) .load("http://img.androidcookie.com/android/test.png") .fitCenter() .into(image); }else{ holder.placeholder.setVisibility(View.INVISIBLE); } } 

我有同样的问题,我解决这个问题:

目标:onViewAttachedToWindow

 @Override public void onViewAttachedToWindow(Holder holder) { super.onViewAttachedToWindow(holder); StructAllItems sfi = mArrayList.get(position); if (!sfi.getPicHayatParking().isEmpty()) { holder.viewFliperMelk.addSlider(new TextSliderView(mContext.getApplicationContext()).image(T.GET_MELK_IMAGE + '/' + sfi.getPicHayatParking() + ".jpg").setScaleType(BaseSliderView.ScaleType.CenterCrop)); } if (!sfi.getPicSleepRoom().isEmpty()) { holder.viewFliperMelk.addSlider(new TextSliderView(mContext.getApplicationContext()).image(T.GET_MELK_IMAGE + '/' + sfi.getPicSleepRoom() + ".jpg").setScaleType(BaseSliderView.ScaleType.CenterCrop)); } if (!sfi.getPicSalonPazirayi().isEmpty()) { holder.viewFliperMelk.addSlider(new TextSliderView(mContext.getApplicationContext()).image(T.GET_MELK_IMAGE + '/' + sfi.getPicSalonPazirayi() + ".jpg").setScaleType(BaseSliderView.ScaleType.CenterCrop)); } if (!sfi.getPicNamayeStruct().isEmpty()) { holder.viewFliperMelk.addSlider(new TextSliderView(mContext.getApplicationContext()).image(T.GET_MELK_IMAGE + '/' + sfi.getPicNamayeStruct() + ".jpg").setScaleType(BaseSliderView.ScaleType.CenterCrop)); } }