shihpeng
shihpeng

Reputation: 5381

What's the difference between the two kinds of implementation of the getView()?

Can anyone please explain what's the difference between the two kinds of getView() implementation?

The first one simply check if the convertView is null; if it's null, inflate a new View object. Then set the sub-Views with proper values.

@Override
public View getView(int position, View convertView, ViewGroup parent) 
{           
    if(convertView == null)
    {
        LayoutInflater inflater = context.getLayoutInflater();
        convertView = inflater.inflate(R.layout.itemlayout, null, true);
    }   

    ImageView image = (ImageView) convertView.findViewById(R.id.icon);
    TextView text = (TextView) convertView.findViewById(R.id.name);     

    MyItem item = items[position];
    text.setText(item.name);
    if("male".equals(item.gender))
    {
        image.setImageResource(R.drawable.male);
    }
    else if("female".equals(item.gender))
    {
        image.setImageResource(R.drawable.female);
    }

    return convertView;
}

The second one is the so-called "ViewHolder" pattern. Many developers say that this method saves a lot of memory and CPU time. But the first implementation also checks the existence of the convertView. Doesn't the first method save some memory? Can anyone explain the difference between the two implementations more deeply and clearly? Thanks very much.

@Override
public View getView(int position, View convertView, ViewGroup parent) 
{       
    ViewHolder holder;

    View itemView = convertView;
    if(itemView == null)
    {
        LayoutInflater inflater = context.getLayoutInflater();
        itemView = inflater.inflate(R.layout.itemlayout, null, true);
        holder = new ViewHolder();
        holder.image = (ImageView) itemView.findViewById(R.id.icon);
        holder.text = (TextView) itemView.findViewById(R.id.name);
        itemView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) itemView.getTag();
    }

    MyItem item = items[position];
    holder.text.setText(item.name);
    if("male".equals(item.gender))
    {
        holder.image.setImageResource(R.drawable.male);
    }
    else if("female".equals(item.gender))
    {
        holder.image.setImageResource(R.drawable.female);
    }

    return itemView;
}

Upvotes: 4

Views: 1158

Answers (2)

BFil
BFil

Reputation: 13096

The second pattern creates a static instance of the ViewHolder and attach it to the view item the first time it is loaded, and then it will be retrieved from that view tag on the future calls

getView() is called very frequently, expecially when you scroll big lists of elements, in fact it is called each time a listview item becomes visible on scroll.

That prevents findViewById() to being called lots of times uselessy, keeping the views on a static reference, it is a good pattern to save some resources (expecially when you need to reference many views in your listview items).

Upvotes: 5

DArkO
DArkO

Reputation: 16110

using a viewHolder prevents findviewById() to be called each time a view needs to be bound on the screen. This means the view is inflated and the resources connected to it are initialized just once(inflation, findById, listeners , content that wont change like static titles or something). so using this gives better performance when working with lists thus the always recomended method.

Upvotes: 1

Related Questions