RecyclerView适配器显示错误的图像

use*_*746 15 android android-layout android-xml android-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://www.website.com/test.png")
                .fitCenter()
                .into(image);
            holder.placeholder.addView(test);
        }
    }

    @Override
    public int getItemCount() {
        return mDataset.size();
    }

}
Run Code Online (Sandbox Code Playgroud)

但是,RecyclerView中的某些项目不应显示图像.我怎么能阻止这种情况发生?

我做检查if (numImages > 0) {onBindViewHolder(),但是这仍然无法从显示该不该有图片的商品图片停止它.

Pra*_*nki 18

您应该imageView.setImageDrawable (null)onBindViewHolder()使用滑行设置图像之前设置In .

将drawable设置为null可以解决问题.

希望能帮助到你!

  • 工作,但它再次加载图像时减慢了滚动速度. (3认同)

Sam*_*udd 14

问题出在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://www.website.com/test.png")
            .fitCenter()
            .into(image);
        holder.placeholder.addView(test);
    }
Run Code Online (Sandbox Code Playgroud)

如果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://www.website.com/test.png")
            .fitCenter()
            .into(image);
        holder.placeholder.addView(test);
    } else {
        Glide.clear(image);
    }
Run Code Online (Sandbox Code Playgroud)

当您拨打电话时into(),Glide会为您取消旧的负载.如果你不打电话into(),你必须给clear()自己打电话.

每次对onBindViewHolder的调用都必须包含一个load()呼叫或一个clear()呼叫.


але*_*кей 8

我也遇到了RecyclerView显示错误图像的问题.发生这种情况是因为RecyclerView没有为每个新列表项膨胀视图:而是回收列表项.

通过回收视图,我们可以粗略地理解克隆视图.克隆的视图可能具有先前交互的图像集.

如果您使用Picasso,Glide或其他lib进行异步加载,这尤其公平.这些库保存对ImageView的引用,并在加载图像时在该引用上设置图像.

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

总而言之,我通过限制RecyclerView克隆我的项目视图来解决这个问题:

setIsRecyclable(false)在ViewHolder构造函数中.

现在RecyclerView的工作速度有点慢,但至少图像设置正确.

或者cansel加载图像 onViewRecycled(ViewHolder holde)

  • 特别是对于非常大且重的数据集,建议不要这样做.回答Prashant Solanki是更好的选择. (4认同)

mma*_*ark 5

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

例如,如果您将 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://www.website.com/test.png")
                .fitCenter()
                .into(image);
        }else{
           holder.placeholder.setVisibility(View.INVISIBLE);
        }
    }
Run Code Online (Sandbox Code Playgroud)