Uncached Views

Context

UI

Affects

Efficiency

Problem

Scrolling of ListViews or switching between pages of ViewPager could be slow.

The code used contains a lot of findViewById() calls which are frequently called while scrolling.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater li = (LayoutInflater) getContext().getSystemService(
            Context.LAYOUT_INFLATER_SERVICE);

    final View view = li.inflate(R.layout.objectData, parent, false);

    ((TextView) view.findViewById(android.R.id.text1)).setText("FOO")

    return view;
}

This will inflate a View every time a new view is rendered.

Refactorings

View Holder

Resolves

Efficiency

Affects

Solution

To make ListViews or any view holding views (like ViewPager) more smooth:

You have to create a class ViewHolder that holds all fields of the view:

static class ViewHolder {
  TextView text;
  TextView timestamp;
  ImageView icon;
  ProgressBar progress;
  int position;
}

Then the Adapter is fixed:

class MyAdapter extends ArrayAdapter {
    ...
    @Override
    public View getView(int position, View v, ViewGroup parent) {
        ViewHolder viewHolder;
        if (v == null) {
            LayoutInflater li = (LayoutInflater) getContext().getSystemService(
                    Context.LAYOUT_INFLATER_SERVICE);
            v = li.inflate(R.layout.objectData, parent, false);
            viewHolder = new ViewHolder();
            viewHolder.txText = (TextView) v.findViewById(R.id.vText);
            viewHolder.txTimestamp = (TextView) v.findViewById(R.id.vTimestamp);
            viewHolder.txIcon = (TextView) v.findViewById(R.id.vIcon);
            viewHolder.txProgress = (TextView) v.findViewById(R.id.vProgress);
            viewHolder.txPosition = (TextView) v.findViewById(R.id.vPosition);
            v.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) v.getTag();
        }
        // access fields and populate with data
        viewHolder.txtText(...)
        return v;
    }
}

Links

Use convertView

Resolves

Efficiency

Affects

Solution

The use of the already inflated convertView parameter is faster:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater li = (LayoutInflater) getContext().getSystemService(
            Context.LAYOUT_INFLATER_SERVICE);

    if(convertView == null) {
        convertView = li.inflate(R.layout.objectData, parent, false);
    }
    ((TextView) convertView.findViewById(android.R.id.text1)).setText("FOO")

    return convertView;
}

Links

Related