Mobile Zone is brought to you in partnership with:

Android developer. I like to share some stuff on my blog. Antoine is a DZone MVB and is not an employee of DZone and has posted 5 posts at DZone. You can read more from them at their website. View Full User Profile

Android ListView Optimizations Part 1: The ViewHolder

11.12.2013
| 12870 views |
  • submit to reddit

When you develop on Android, you will probably need to make lists pretty quickly. However, it can be complicated to understand all the mechanisms when you are a beginner. This series of posts aims to give you tips if you want to increase the smoothness of your lists.

This first post is a basic one which talks about a well known tip, called ViewHolder. This is absolutely essential if you want to have a viable list. But we must first understand how it works.

A list is composed of elements displayed in views; which ones are declared in XML files (generally). Usually, a list is composed of elements whose views are the same, only the content changes. That’s why we use the same view for all the elements. The role of the adapter is to provide views to the list. It has to create and modify their contents.

Here is an example of a basic custom adapter, providing elements with a name and a description:

public class MyAdapter extends BaseAdapter {

    private LayoutInflater mLayoutInflater;
    private List mData;

    public MyAdapter(Context context, List data){
        mData = data;
        mLayoutInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return mData == null ?  : mData.size();
    }

    @Override
    public MyPojo getItem(int position) {
        return mData.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View view, ViewGroup parent) {

        //This is bad, do not do this at home
        View vi = mLayoutInflater.inflate(R.layout.item, parent, false);

        TextView tvName = (TextView) vi.findViewById(R.id.textView_item_name);
        TextView tvDescription = (TextView) vi.findViewById(R.id.textView_item_description);

        MyPojo item = getItem(position);

        tvName.setText(item.getName());
        tvDescription.setText(item.getDescription());

        return vi;
    }
}

That is the code we could make when we don’t know that listviews recycle their views. Indeed, when you scroll down, the views disappearing on the top are reused to display items on the bottom of your list. I hope that this is clear because it’s very important :p. As a consequence, we will tag our views in order to avoid inflating views that already exist (this operation takes a long time).

We will write a class (called ViewHolder) in which references between the widgets will be saved:

static class ViewHolder{
    TextView tvName;
    TextView tvDescription;
}

And the adapter:

@Override
public View getView(int position, View view, ViewGroup parent) {

  View vi = view;             //trying to reuse a recycled view
  ViewHolder holder = null;

  if (vi == null) {
      //The view is not a recycled one: we have to inflate
      vi = mLayoutInflater.inflate(R.layout.item, parent, false);
      holder = new ViewHolder();

      holder.tvName = (TextView) vi.findViewById(R.id.textView_item_name);
      holder.tvDescription = (TextView) vi.findViewById(R.id.textView_item_description);
      vi.setTag(holder);
  } else {
      // View recycled !
      // no need to inflate
      // no need to findViews by id
      holder = (ViewHolder) vi.getTag();
  }

  MyPojo item = getItem(position);

  holder.tvName.setText(item.getName());
  holder.tvDescription.setText(item.getDescription());

  return vi;
}

If you want to add other widgets in your elements (an image for example), you will have to add them in the ViewHolder too.

That’s all - I’ll talk next time about the way you can optimize your images in your lists (LRUCache, etc.).


Published at DZone with permission of Antoine Merle, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)