Over a million developers have joined DZone.
Platinum Partner

Android ListView Optimizations Part 1: The ViewHolder

The role of the adapter is to provide views to the list.

· Mobile Zone

The Mobile Zone is brought to you in partnership with Strongloop and IBM.  Learn how IBM API Connect simplifies your API lifecycle for hybrid cloud with Node.js and Java.

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.).


The Mobile Zone is brought to you in partnership with Strongloop and IBM.  Visually compose APIs with easy-to-use tooling. Learn how IBM API Connect provides near-universal access to data and services both on-premises and in the cloud.

Topics:
java,mobile,architecture,tips and tricks,tools & methods

Published at DZone with permission of Antoine Merle , DZone MVB .

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}