Why is the content of CardView inside a RecyclerView (in my case) changing when I scroll?

Tags: , , , ,



I have the same question like this post “Cardview’s data are changed while scrolling RecyclerView”.

But taking out the statics isn’t working.

Context of what I am doing:

I am adding a couple of buttons inside a FlexboxLayout and again inside a CardView (CardView inside a RecyclerView). Buttons are being added dynamically.

The same thing happens with a couple of TextView, which I add after Buttons to CardView.

Problem:

Buttons and TextViews are being Multiplied, while I Scroll.

Context of different CardViews are being exchanged, while scrolling.

Video: https://sendvid.com/adugp8vh

What I am using:

RecyclerView is inside one of my Fragments (ConstraintLayout), in which I defined the recycler Adapter.

This is my adapter

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.MyViewHolder> {
ArrayList<DataModel> dataSet = new ArrayList<DataModel>();
Context currentContext;

public class MyViewHolder extends RecyclerView.ViewHolder {

    public Button datumButton;
    public FlexboxLayout matchedWordsLayout;
    public LinearLayout textviewLayout;



    public MyViewHolder(View itemView) {
        super(itemView);
        this.datumButton = (Button) itemView.findViewById(R.id.datumButton);
        this.matchedWordsLayout = (FlexboxLayout) itemView.findViewById(R.id.matchedWordsLayout);
        this.textviewLayout = (LinearLayout) itemView.findViewById(R.id.textviewLayout);

    }
}


public CustomAdapter(ArrayList<DataModel> data, Context currentContext) {
    this.dataSet = data;
    // currentContext not getting it from here

}

@NonNull
@Override
public CustomAdapter onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    View view =  LayoutInflater.from(parent.getContext())
            .inflate(R.layout.positive_result_card, parent, false);

    MyViewHolder myViewHolder = new MyViewHolder(view);
    this.currentContext = parent.getContext();
    return myViewHolder;
}


@RequiresApi(api = Build.VERSION_CODES.O)
//@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int listPosition) {
    Button DatumButton = holder.datumButton;
    FlexboxLayout MatchedWordsLayout = holder.matchedWordsLayout;
    LinearLayout TextviewLayout = holder.textviewLayout;

    //Modify the button for date
    ArrayList <String> TTMMYY = dataSet.get(listPosition).getDatum();
    String Datum = String.join(".", TTMMYY);
    DatumButton.setText(Datum);
    DatumButton.setTag(Datum);
  

  



    // add button for each word
    ArrayList <String>  ButtonNames = dataSet.get(listPosition).getButtonnames();

    for (String Buttonname : ButtonNames) {
        Button sampleButton = new Button(currentContext);
        sampleButton.setText(Buttonname);
        sampleButton.setTag(Datum); 

        MatchedWordsLayout.addView(sampleButton);
    }

    
    ArrayList <String> textLines = dataSet.get(listPosition).getTextLines();
    

   
    for (String satzt : textLines){
        TextView sampleTextView = new TextView(currentContext);
        sampleTextView.setText(satzt);

        TextviewLayout.addView(sampleTextView);
    }





}

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

My text has probably mistakes

Answer

You are adding Views programmatically on every bind, but you never remove them, so each bind just adds more (remember that ViewHolders are re-used, so the Buttons and TextViews you added last time are still there). To fix it, remove all the children from the ViewGroups before you add the new children:

    // Added: remove all the children before we add more
    MatchedWordsLayout.removeAllViews();

    for (String Buttonname : ButtonNames) {
        Button sampleButton = new Button(currentContext);
        sampleButton.setText(Buttonname);
        sampleButton.setTag(Datum); 

        MatchedWordsLayout.addView(sampleButton);
    }

    
    ArrayList <String> textLines = dataSet.get(listPosition).getTextLines();
    
    // Added: remove all the children before we add more
    TextviewLayout.removeAllViews();

    for (String satzt : textLines){
        TextView sampleTextView = new TextView(currentContext);
        sampleTextView.setText(satzt);

        TextviewLayout.addView(sampleTextView);
    }


Source: stackoverflow