Подтвердить что ты не робот

Адаптер 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();
    }

}

Однако некоторые элементы в RecyclerView показывают изображения, когда их не должно быть. Как я могу остановить это?

Я делаю чек if (numImages > 0) { в onBindViewHolder(), но это все еще не останавливает его от показа изображений для элементов, которые не должны иметь изображений.

4b9b3361

Ответ 1

Вы должны установить imageView.setImageDrawable (null) В onBindViewHolder() перед установкой изображения с помощью глиссады.

Настройка изображения, которое можно удалить, чтобы устранить проблему.

Надеюсь, что это поможет!

Ответ 2

У меня также были проблемы с RecyclerView, отображающими неправильные изображения. Это происходит потому, что RecyclerView не раздувает представление для каждого нового элемента списка: вместо этого элементы списка перерабатываются.

При просмотре видов обработки мы можем без труда понять представления клонирования. Клонированный вид может иметь изображение, установленное в предыдущем взаимодействии.

Это особенно справедливо, если вы используете Picasso, Glide или какую-либо другую lib для асинхронной загрузки. Эти библиотеки содержат ссылку на ImageView и устанавливают изображение при этом повторении при загрузке изображения.

К моменту загрузки изображения представление элемента может быть клонировано, и изображение будет установлено на неправильный клон.

Короче говоря, я решил эту проблему, ограничив RecyclerView от клонирования представлений моих позиций:

setIsRecyclable(false) в конструкторе ViewHolder.

Теперь RecyclerView работает немного медленнее, но по крайней мере изображения установлены правильно.

Или загрузите изображение cansel в onViewRecycled(ViewHolder holde)

Ответ 3

Проблема в 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);
    }

Если numImages равно 0, вы просто разрешаете ранее загруженную загрузку в представление, которое вы повторно используете для продолжения. Когда он закончится, он все равно загрузит старое изображение в ваше представление. Чтобы предотвратить это, скажите Glide, чтобы отменить предыдущую загрузку, вызывая clear:

   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);
    }

Когда вы вызываете into(), Glide обрабатывает отмену старой загрузки для вас. Если вы не назовете into(), вы должны позвонить clear() самостоятельно.

Каждый вызов onBindViewHolder должен включать либо вызов load(), либо вызов clear().

Ответ 4

Проблема заключается в том, что, поскольку вы работаете с представлениями, которые будут переработаны, вам нужно будет обрабатывать все возможные сценарии в момент привязки вашего представления.

Например, если вы добавляете ImageView в LinearLayout в позицию 0 источника данных, то, если позиция 4 не удовлетворяет условию, его вид, скорее всего, будет иметь ImageView, добавленный при позиции привязки 0.

Вы можете добавить содержимое содержимого 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);
        }
    }

Ответ 5

У меня была такая же проблема, и я исправил ее так:

ЦЕЛЬ: 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));
    }
}