RecyclerView перетасовки предметов

Я знаю, что этот вопрос задавался несколько раз, но проблема все еще присутствует. Так что дело в том, что когда я прокручиваю свою вертикаль RecyclerView элементы списка внутри ViewHolder тасуются. У меня есть список некоторых объектов с логическим внутри него, решая ViewTypeтак что я могу раздувать разные взгляды. Итак, вот код:

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    if(viewType == TYPE_ACTIVE) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_poll_item_active, parent, false);
        return new CardViewHolderActive(view);

    } else if(viewType == TYPE_INACTIVE) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_poll_item_past, parent, false);
        return new CardViewHolderPast(view);
    }

    throw new RuntimeException("There is no type that matches the type " + viewType + " + make sure your using types correctly");

}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {

    Poll poll = mListPollObjects.get(position);
    Log.d("ADAPTER", "position - " + position);
    if(holder instanceof CardViewHolderActive) {
        ((CardViewHolderActive) holder).bindActivePolls(poll);

    } else if(holder instanceof CardViewHolderPast) {

        if(position == 0) {
            ((CardViewHolderPast) holder).bindPastPolls(poll, true);

        } else if(getItemViewType(position - 1) == TYPE_INACTIVE) {
            ((CardViewHolderPast) holder).bindPastPolls(poll, false);

        } else if(getItemViewType(position - 1) == TYPE_ACTIVE)
            ((CardViewHolderPast) holder).bindPastPolls(poll, true);
    }

}

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


/**
 * Added to solve the RecyclerView shuffling problem.
 *
 * @param position
 * @return
 */
@Override
public long getItemId(int position) {
    return position;
}

/**
 * Added to solve the RecyclerView shuffling problem.
 *
 * @param position
 * @return
 */

@Override
public int getItemViewType(int position) {
    Poll poll = mListPollObjects.get(position);

    if(poll.getStatus().equals(Poll.STATUS_ACTIVE)) {
        return TYPE_ACTIVE;
    } else {
        return TYPE_INACTIVE;
    }
}

Итак, когда у меня было:

@Override
public int getItemViewType(int position) {
    return position;
}

перетасовка исчезла, однако я должен был сделать обязательные вещи в onBindViewHolder все вручную, поэтому я решил переключиться на viewTypes, Я действительно не могу понять, что здесь происходит, и это довольно раздражает... Надеюсь, я предоставил достаточно информации. Заранее спасибо!

Здесь bindActivePolls метод из CardViewHolderActive:

public void bindActivePolls(final Poll polls) {

        int listImageSize = polls.getListImageObjects().size();

        //tvPollTitle.setText(polls.getStatus() + " - " + polls.getId());

        if(polls.getTitle() != null || !polls.getTitle().equals("")) {
            tvPollTitle.setText(polls.getTitle());
        } else {
            tvPollTitle.setText("");
        }

        tvCurrentVotes.setText(String.valueOf(polls.getVotesCount()) + "/");
        tvUpToVotes.setText(String.valueOf(polls.getMaxVotes()));

        // Setting the percentage bars.

        pbProgressOne.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(0).getVotes()));
        tvProgressOne.setText(String.valueOf(pbProgressOne.getProgress()) + mContext.getString(R.string.percentage));

        pbProgressTwo.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(1).getVotes()));
        tvProgressTwo.setText(String.valueOf(pbProgressTwo.getProgress()) + mContext.getString(R.string.percentage));

        GlideApp.with(mContext)
                .asDrawable()
                .load(polls.getListImageObjects().get(0).getUrlImageMainThumbnail())
                .transforms(new CenterCrop(), new RoundedCorners(20))
                .into(ivImageOne);

        GlideApp.with(mContext)
                .asDrawable()
                .load(polls.getListImageObjects().get(1).getUrlImageMainThumbnail())
                .transforms(new CenterCrop(), new RoundedCorners(20))
                .into(ivImageTwo);

        if(listImageSize >= 3) {

            pbProgressThree.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(2).getVotes()));
            tvProgressThree.setText(String.valueOf(pbProgressThree.getProgress()) + mContext.getString(R.string.percentage));

            GlideApp.with(mContext)
                    .asDrawable()
                    .load(polls.getListImageObjects().get(2).getUrlImageMainThumbnail())
                    .transforms(new CenterCrop(), new RoundedCorners(20))
                    .into(ivImageThree);
        }
        if(listImageSize >= 4) {

            pbProgressFour.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(3).getVotes()));
            tvProgressFour.setText(String.valueOf(pbProgressFour.getProgress()) + mContext.getString(R.string.percentage));

            GlideApp.with(mContext)
                    .asDrawable()
                    .load(polls.getListImageObjects().get(3).getUrlImageMainThumbnail())
                    .transforms(new CenterCrop(), new RoundedCorners(20))
                    .into(ivImageFour);
        }


    }

А также bindPastPolls() от CardViewHolderPast:

public void bindPastPolls(Poll polls, boolean isFirstPast) {


        if(isFirstPast) {
            vSeparator.setVisibility(View.VISIBLE);
            tvPastContestSeparator.setVisibility(View.VISIBLE);
        }

        int listImageSize = polls.getListImageObjects().size();
        //tvPollTitle.setText(polls.getStatus() + " - " + polls.getId());
        if(polls.getTitle() != null || !polls.getTitle().equals("")) {
            tvPollTitle.setText(polls.getTitle());
        } else {
            tvPollTitle.setText("");
        }
        tvCurrentVotes.setText(String.valueOf(polls.getVotesCount()) + "/");
        tvUpToVotes.setText(String.valueOf(polls.getMaxVotes()));

        pbProgressOne.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(0).getVotes()));
        tvProgressOne.setText(String.valueOf(pbProgressOne.getProgress()) + mContext.getString(R.string.percentage));

        pbProgressTwo.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(1).getVotes()));
        tvProgressTwo.setText(String.valueOf(pbProgressTwo.getProgress()) + mContext.getString(R.string.percentage));



        GlideApp.with(mContext)
                .asDrawable()
                .load(polls.getListImageObjects().get(0).getUrlImageMainThumbnail())
                .transforms(new CenterCrop(), new RoundedCorners(20))
                .into(ivImageOne);

        GlideApp.with(mContext)
                .asDrawable()
                .load(polls.getListImageObjects().get(1).getUrlImageMainThumbnail())
                .transforms(new CenterCrop(), new RoundedCorners(20))
                .into(ivImageTwo);

        if(listImageSize >= 3) {

            pbProgressThree.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(2).getVotes()));
            tvProgressThree.setText(String.valueOf(pbProgressThree.getProgress()) + mContext.getString(R.string.percentage));

            GlideApp.with(mContext)
                    .asDrawable()
                    .load(polls.getListImageObjects().get(2).getUrlImageMainThumbnail())
                    .transforms(new CenterCrop(), new RoundedCorners(20))
                    .into(ivImageThree);
        }
        if(listImageSize >= 4) {

            pbProgressFour.setProgress(votePercentageCalculator(polls.getVotesCount(), polls.getListImageObjects().get(3).getVotes()));
            tvProgressFour.setText(String.valueOf(pbProgressFour.getProgress()) + mContext.getString(R.string.percentage));

            GlideApp.with(mContext)
                    .asDrawable()
                    .load(polls.getListImageObjects().get(3).getUrlImageMainThumbnail())
                    .transforms(new CenterCrop(), new RoundedCorners(20))
                    .into(ivImageFour);
        }

    }

Обновление: когда я установил holder.setIsRecyclable(false) это работает должным образом, но я предполагаю, что теряет свое основное назначение RecyclerView?

2 ответа

У меня тоже была эта проблема несколько лет назад, и это потому, что я использовал glide, если есть изображение из API, а если нет, то я не устанавливал изображение. Я добавил оператор else, чтобы указать src для представления изображения. Если вы хотите, чтобы он был пустым, установите src, который соответствует фону.

В Java

      @Override
public int getItemViewType(int position)
{
    return position;
}

В Котлине

      override fun getItemViewType(position: Int): Int = position