Search code examples
androidperformancelistviewconvertview

Listview with or without convertview == null


I have a dilemma using

if (convertview==null){
(my code)
}

or not. Without this piece of code, my listview is not very fast, it locks for a few ms sometimes and you can easy notice this in use. It just doesn't work how its meant to work.

But when this piece of code, my listitems will start recounting after a while (10 or so) and i have a few returning listitems in my list (with the header i used). I used this tutorial for getting my listview with sections link. The length of the list is good.

Ofcourse my list is totally useless with a view repeating items (nicely sectioned by the way) but i also dont want it to be slow. Does anyone know what to do? Below is my adapter:

public class DelftAdapter extends BaseAdapter {

private Activity activity;
private  List<ListItem> listItems;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader; 
private final int[] bgColors = new int[] { R.color.list_odd, R.color.list_even };


public DelftAdapter(Activity a, ArrayList<ListItem> li) {
    activity = a;
    listItems = li;
    inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    imageLoader=new ImageLoader(activity.getApplicationContext());

}

public int getCount() {
    return listItems.size();
}

public Object getItem(int position) {
    return position;
}

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




public View getView(int position, View convertView, ViewGroup parent) {
    View vi=convertView;


        final ListItem li = listItems.get(position); 
        if (li != null) {
            if(li.isSection()){ // is sectionheader
                SectionItem si = (SectionItem)li; 
                vi = inflater.inflate(R.layout.sectionedlistitem, null);
                vi.setOnClickListener(null);
                vi.setOnLongClickListener(null);
                vi.setLongClickable(false);
                final TextView sectionView = (TextView) vi.findViewById(R.id.list_header_title);
                sectionView.setText(si.getTitle());
            }else{ // no sectionheader
                ListData ld = (ListData)li;
            vi = inflater.inflate(R.layout.singlelistitem, null);
        TextView tvNames=(TextView)vi.findViewById(R.id.tvname); 
        TextView tvTip=(TextView)vi.findViewById(R.id.tvtip);
        ImageView image=(ImageView)vi.findViewById(R.id.image);
        tvNames.setText(ld.name);
        tvTip.setText(ld.tip);
            if (listItems.get(position) != null ){
                imageLoader.DisplayImage(ld.photoUrl, image);
                }
                else{
                image.setImageURI(Uri.fromFile(new File("//assets/eten.png")));
            }
        // alternating colors
        int colorPos = position % bgColors.length;
             vi.setBackgroundResource(bgColors[colorPos]);
            }
    }
        return vi;

}
}

Solution

  • Consider using getItemViewType() and getViewTypeCount() with recycling convertView. Those are used when you have list items with various layouts. You definitely should recycle convertView.

    See also http://android.amberfog.com/?p=296

    In your case:

        private static final int TYPE_ITEM = 0;
        private static final int TYPE_SECTION = 1;
    
        @Override
        public int getItemViewType(int position) {
            return listItems.get(position).isSection() ? TYPE_SECTION : TYPE_ITEM
        }
    
        @Override
        public int getViewTypeCount() {
            return 2;  // sectionheader and regular item
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            int type = getItemViewType(position);
            if (convertView == null) {
                switch (type) {
                    case TYPE_ITEM:
                        convertView = mInflater.inflate(R.layout.singlelistitem, null);
                        ...
                        break;
                    case TYPE_SECTION:
                        convertView = mInflater.inflate(R.layout.sectionedlistitem, null);
                        ...
                        break;
                }
            } else {
                ...
            }
            return convertView;
        }
    

    Also use ViewHolder pattern to achieve better performance.