Search code examples
javafirebaseandroid-recyclerviewandroid-adapterandroid-viewholder

Bug with the recycle view and the viewholder adapater in Android


I am getting a very strange bug in my application. To make it more clear I will create a similar example with minus code.

I am reading objects from Firebase Realtime Database with an addListenerForSingleValueEvent. While I am reading the objects, I am stored them in an Array that I passed to an Adapter in a Recycleview. At this point, I can say, after debugging, that all seems to work correctly.

Then in the Adapter, I have a code similar to this:

public class AdapterObject extends RecyclerView.Adapter<AdapterObject.ViewHolder> {

    ArrayList<Object> objectList;
    Context mContext;

    public AdapterObject (Context context, ArrayList<Object> objectList){
        this.mContext = context;
        this.objectList = objectList;
    }

    @NonNull
    @Override
    public AdapterObject.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.object_grid_layout, parent,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull AdapterObject.ViewHolder holder, int position) {
        Object o = objectList.get(position);
        Log.d("TAG", o.getAtribute());
        if (o.getAtribute().equals("A")){
            holder.atribute.setVisibility(View.VISIBLE);
        }

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

    public static class ViewHolder extends RecyclerView.ViewHolder {

        TextView atribute;

        boolean favorite;
        String descuento, precioOriginal;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            atribute = itemView.findViewById(R.id.atribute);
        }
    }
}

As you can see in the code if the current object has the attribute value == "A", then his Textview is displayed, otherwise, the Textview remains hidden.

All seems correct when I debug it because the objects and their attribute corresponds to the Database, but when I deploy the application in the Android simulator and I start going up and down on the Recycleview, the holders start to display the Textviews although the console debugs seems correct...

Is this normal in RecycleViews? How can I fix that? I have found this, do you think it has any relation?


Solution

  • This is an extract from the RecyclerView documentation

    As the name implies, RecyclerView recycles those individual elements. When an item scrolls off the screen, RecyclerView doesn't destroy its view. Instead, RecyclerView reuses the view for new items that have scrolled onscreen. This reuse vastly improves performance, improving your app's responsiveness and reducing power consumption.

    That means that when the view gets reused it will keep the current properties. It's up to you to change them when onBindViewHolder gets called.

    In your specific case

    @Override
    public void onBindViewHolder(@NonNull AdapterObject.ViewHolder holder, int position) {
        Object o = objectList.get(position);
        Log.d("TAG", o.getAtribute());
        if (o.getAtribute().equals("A")){
            holder.atribute.setVisibility(View.VISIBLE);
        } else. {
            holder.atribute.setVisibility(View.GONE);
        }
      }