0

I have a recyclerview which presents a list of cards. All cards are based on the same XML file but depending on the data received from JSON, some parts of the card are hidden (some include images, some images and text, some a date, etc.

The recyclerview script is as follows:

public class FeedRecyclerViewAdapter extends RecyclerView.Adapter<FeedRecyclerViewAdapter.ViewHolder>  {
private Context context;
private List<FeedItem> feedList;

public FeedRecyclerViewAdapter(Context context, List<FeedItem> feedList) {
    this.context = context;
    this.feedList = feedList;
}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext())
            .inflate(R.layout.feed_card, viewGroup, false);
    return new ViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
    String imageUrl;

    FeedItem feedItem = feedList.get(i);
    String feedType = feedItem.getItemType();

    if (feedType.equals("video")) {
        viewHolder.feedDate.setText(feedItem.getItemDate());
        viewHolder.feedTitle.setText(feedItem.getItemTitle());
        viewHolder.feedText.setText(feedItem.getItemText());

        Picasso.get().load(feedItem.getItemLink()).into(viewHolder.feedPhoto);
    } else if (feedType.equals("photo")) {

        viewHolder.feedDate.setVisibility(View.GONE);
        viewHolder.feedTitle.setVisibility(View.GONE);
        viewHolder.feedText.setVisibility(View.GONE);

        Picasso.get().load(feedItem.getItemLink()).into(viewHolder.feedPhoto);
    } else if (feedType.equals("blog")) {

        viewHolder.feedDate.setVisibility(View.GONE);
        viewHolder.feedTitle.setText(feedItem.getItemTitle());
        viewHolder.feedText.setText(feedItem.getItemText());

        Picasso.get().load(feedItem.getItemLink()).into(viewHolder.feedPhoto);
    }
}

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

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    public TextView feedDate, feedTitle, feedText;
    public ImageView feedPhoto;

    public ViewHolder(@NonNull View itemView) {
        super(itemView);

        

        feedDate = itemView.findViewById(R.id.feedDate);
        feedTitle = itemView.findViewById(R.id.feedTitle);
        feedText = itemView.findViewById(R.id.feedText);
        feedPhoto = itemView.findViewById(R.id.feedPhoto);
    }

    
}
}

The feed loads properly, but when I start scrolling I noticed that some items in the card disappear, like it will show the image but not the text, when I scroll back up, it changes again.

I believe I'm not setting things properly in onBindViewHolder but not sure how to do it the right way.

I'm working on Android Studio 4.1 with Java.

cesarcarlos
  • 1,271
  • 1
  • 13
  • 33
  • 4
    ViewHolders get reused. This means you need to set every property you potentially modify. All the Views you set to `View.GONE` never get set to visible again if they get reused for a different item type – JensV Dec 23 '20 at 16:44
  • @JensV Your comment is the correct answer. You should create an answer for this question containing your comment. – David Wasser Dec 23 '20 at 16:45
  • Thanks @JensV that did the trick. If you post it as an answer I can accept it! – cesarcarlos Dec 23 '20 at 16:51
  • Also, you could use a different approach and use a recycler view with multiple view types. The code would be a little longer, but clearer and easier to maintain. – lpizzinidev Dec 23 '20 at 17:12

1 Answers1

0

ViewHolders get reused. This means you need to set every property you potentially modify. All the Views you set to View.GONE never get set to visible again if they get reused for a different item type.

As pointed out by luca_999, you can also utilize ViewTypes for this behaviour as described in this answer. This is more efficient when your binding code gets expensive when changing between types or when you need to inflate different layouts.

JensV
  • 3,997
  • 2
  • 19
  • 43