0

What is the utility of ViewHolder in a custom Adapter ?

I have created an Adapter using the ViewHolder and an other without and I have the same result... so what is the utility of this ?


This is my CustomAdapter.class with the ViewHolder :

public class CustomAdapter extends ArrayAdapter<Fruit> {

    public class ViewHolder {
        TextView txtName;
        TextView txtColor;
    }

    CustomAdapter(Context context, ArrayList<Fruit> data) {
        super(context, R.layout.item_fruit, data);
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {

        final Fruit fruit = getItem(position);

        ViewHolder viewHolder = new ViewHolder();

        if (convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(R.layout.item_fruit, parent, false);
        }

        viewHolder.txtName = (TextView) convertView.findViewById(R.id.textView_fruit_name);
        viewHolder.txtColor = (TextView) convertView.findViewById(R.id.textView_fruit_color);

        if (fruit != null) {
            viewHolder.txtName.setText(fruit.getName());
            viewHolder.txtColor.setText(fruit.getColor());
        }

        return convertView;
    }
}

This is my CustomAdapter.class without the ViewHolder :

public class CustomAdapter extends ArrayAdapter<Fruit> {

    CustomAdapter(Context context, ArrayList<Fruit> data) {
        super(context, R.layout.item_fruit, data);
    }

    @NonNull
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {

        final Fruit fruit = getItem(position);

        if (convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(getContext());
            convertView = inflater.inflate(R.layout.item_fruit, parent, false);
        }

        TextView txtName = (TextView) convertView.findViewById(R.id.textView_fruit_name);
        TextView txtColor = (TextView) convertView.findViewById(R.id.textView_fruit_color);

        if (fruit != null) {
            txtName.setText(fruit.getName());
            txtColor.setText(fruit.getColor());
        }

        return convertView;
    }
}
Jéwôm'
  • 3,753
  • 5
  • 40
  • 73
  • You're not using the viewholder pattern correctly. You need to initialize the viewholder and views inside the `if(convertView==null)` block and use `setTag` and `getTag` to retrieve the viewHolder – ashkhn May 03 '17 at 08:42
  • Here is a better explained answer to your question
    [Link](http://stackoverflow.com/questions/21501316/what-is-the-benefit-of-viewholder)
    – Sandeep dhiman May 03 '17 at 08:45

1 Answers1

1

To use ViewHolder correctly, you need to change your code to something like:

@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {

    final Fruit fruit = getItem(position);

    if (convertView == null) {
        LayoutInflater inflater = LayoutInflater.from(getContext());
        convertView = inflater.inflate(R.layout.item_fruit, parent, false);
        convertView.setTag(new ViewHolder(convertView));
    }

    ViewHolder viewHolder = (ViewHolder) convertView.getTag();

    viewHolder.txtName = (TextView) convertView.findViewById(R.id.textView_fruit_name);
    viewHolder.txtColor = (TextView) convertView.findViewById(R.id.textView_fruit_color);

    if (fruit != null) {
        viewHolder.txtName.setText(fruit.getName());
        viewHolder.txtColor.setText(fruit.getColor());
    }

    return convertView;
}

And your ViewHolder will something like:

private class ViewHolder {
    public TextView txtName;
    public TextView txtColor;

    public ViewHolder(View view) {
        txtName = (TextView) view.findViewById(R.id.txt_name);
        txtColor = (TextView) view.findViewById(R.id.txt_color);
    }
}

Calling findViewById() is expensive, calling it on your views for each call to getView() will waste a lot of time.

The sole advantage of using ViewHolder is to save time by not calling findViewById() when a view is being reused, i.e. when convertView is not null.

Kamran Ahmed
  • 7,661
  • 4
  • 30
  • 55
  • Thanks but in the line convertView.setTag(new ViewHolder(convertView)); , il have an error ViewHolder() in ViewHolder cannot be applied to (android.view.View) – Jéwôm' May 03 '17 at 08:57
  • 1
    Check the updated answer to see how `ViewHolder` is supposed to be written. – Kamran Ahmed May 03 '17 at 08:57