ConvertView being passed in as a view that's still on screen
In my custom ListAdapter, the first time that GetView() is called, convertView is passed in as NULL, but the second time it is passed in as the view that was created the first time. My ListView has 4 rows, and all 4 are on the screen at the same time. From the documentation, it seems that convertView should be a view that was already created and has now been scrolled off the screen. I expected convertView to be null all 4 times, so that it would create / inflate 4 separate views. Am I supposed to have a convertView after the first call to getView? Thanks.
In OnCreate():
Cursor questions = db.loadQuestions(b.getLong("categoryId"), inputLanguage.getLanguageId(), outputLanguage.getLanguageId());
startManagingCursor(questions);
ListAdapter adapter = new QuestionsListAdapter(this, questions);
ListView list = (ListView)findViewById(R.id.list1);
setListAdapter(adapter);
Adapter class
private class QuestionsListAdapter extends BaseAdapter implements ListAdapter{
private Cursor c;
private Context context;
public QuestionsListAdapter(Context context, Cursor c) {
this.c = c;
this.context = context;
}
public Object getItem(int position) {
c.moveToPosition(position);
return new Question(c);
}
public long getItemId(int position) {
c.moveToPosition(po开发者_开发技巧sition);
return new Question(c).get_id();
}
@Override
public int getItemViewType(int position) {
Question currentQuestion = (Question)this.getItem(position);
if (currentQuestion.getType().equalsIgnoreCase("text"))
return 0;
else if (currentQuestion.getType().equalsIgnoreCase("range"))
return 0;
else if (currentQuestion.getType().equalsIgnoreCase("yesNo"))
return 2;
else if (currentQuestion.getType().equalsIgnoreCase("picker"))
return 0;
else if (currentQuestion.getType().equalsIgnoreCase("command"))
return 0;
else if (currentQuestion.getType().equalsIgnoreCase("datePicker"))
return 0;
else if (currentQuestion.getType().equalsIgnoreCase("diagram"))
return 0;
else
return -1;
}
@Override
public int getViewTypeCount() {
return 7;
}
public int getCount() {
return c.getCount();
}
public View getView(int position, View convertView, ViewGroup viewGroup) {
Question currentQuestion = (Question)this.getItem(position);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.question_row_text, null);
}
//setup cell
return convertView;
}
}
If I remember right, GetView
will be called twice for each row that's to be displayed. I think that the first set of calls is done for layout purposes, and the second set returns the views that will actually be displayed. It makes sense that the second set of calls should return the same Views that were returned in the first set of calls.
In any case, your code should not care whether it's being called for layout or display. In almost all situations, if the convertView
is non-null, then normally that convertView
should be returned; otherwise, you should return a new View.
To be honest I can't see much wrong with your code. You might want to try extending CursorAdapter
and just overriding a few methods so that it can manage the cursor for you.
Fast forward to 2014 and I was having the same problem... None of the solutions in this post worked for me. As I was watching the Google I/O video referenced in above answers and comments, the answer (for my particular case) became immediately obvious at about the 19 minute mark...
THE NUMBER RETURNED FROM GETVIEWTYPECOUNT() MUST REMAIN CONSTANT THROUGHOUT THE LIFE OF THE ADAPTER!!!!
I had created an adapter that could dynamically have any number of types of views/data... and my getViewTypeCount() method returned the current number of view types... so, if I ever added a new data type to the adapter that return value would change.
Making it a constant number fixed my problem. Hopefully this will help other people in the future as well.
精彩评论