I'm trying to wrap my head around getView() and I don't think there's any topic in Android that creates more confusion and questions on StackOverflow and elsewhere. Everyone wants to know why it gets called so many times or in what order or not at all, but as Romain Guy says here , " there is absolutely no guarantee on the order in which getView() will be called nor how many times."
So I have a different question: I don't understand the convertView parameter.
I have a list of 15 items, 11 of which can fit on the screen. The very first time my app starts up getView() is called 48 times.
convertView is null for position 0 on the first call, the non-null for positions 1-11, then non-null for position 0 and null for positions 1-11, then null for position 0 and non-null for positions 1-11, and finally non-null for positions 0-11.
Could someone please explain why/when convertView is null versus non-null, how/why it starts off non-null for most positions, and why the same positions seem to bounce back and forth between these two states?
References to good tutorials, written in clear English, that explain convertView in detail would also be appreciated.
PS - my tests were done on a device running Android 2.3.5, if that matters. I know Google has changed ListActivity/adapter/getView stuff several times since then.
Per request, I'm including the Adapter code (I've obscured some proprietary names). Unfortunately I can't answer any "why did you do that?" questions, since I didn't write it
protected class PLxxxAdapter extends BaseAdapter {
public PLxxxAdapter(Context c) {
}
@Override
public int getCount() {
return listItems.size();
}
@Override
public Object getItem(int position) {
return listItems.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
boolean select;
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.PLxxxitem, null);
//This is still needed even though we point to an XML description
convertView.setLayoutParams(new ListView.LayoutParams(
ListView.LayoutParams.MATCH_PARENT,
ListView.LayoutParams.MATCH_PARENT));
holder = new ViewHolder();
//Get the views of the row
holder.itemView = (TextView)convertView.findViewById(R.id.post);
holder.cV1 = (CheckedTextView)convertView.findViewById(R.id.check1);
//Init the 'confirm' box listener
holder.cV1.setCompoundDrawablesWithIntrinsicBounds(0, R.layout.smallcb, 0, 0);
holder.cV1.setOnClickListener(new ConfBoxListener());
convertView.setTag(holder);
holder.cV1.setTag(holder); //These views need tags for onClick()
}
else {
holder = (ViewHolder)convertView.getTag(); // convertview NOT null
}
try {
int liSize = listItems.size();
if (position < liSize) {
holder.itemView.setText(listItems.get(position));
}
}
catch (Exception e) {
Log.e ("PLxxxActivity.getView Crash", "details " + e);
}
holder.cV1.setChecked(confirmed.get(position));
select = selected.get(position);
if (select == true) {
convertView.setBackgroundResource(R.color.colBlue);
}
else
convertView.setBackgroundResource(R.color.colGrey);
holder.position = position;
if (RemoteControlActivity.confCBs == true)
holder.cV1.setVisibility(View.VISIBLE);
else
holder.cV1.setVisibility(View.INVISIBLE);
return convertView;
} // end getView
} //end class PLxxxAdapter