I’m using the ViewHolder pattern with a CursorAdapter to populate a ListView. I’m trying to store an integer in my ViewHolder that corresponds to a value in a column from my cursor. Later I want to iterate over all the items in my ListView and pull out this value.
However, it appears that when the CursorAdapter recycles my views, it doesn’t update the integer value in my ViewHolder.
Here is the relevant code in my CursorAdapter (I’m using Mono For Android, so the code is C#, but the idea is the same).
public override void BindView(View view, Context context, ICursor cursor)
{
var viewHolder = view.Tag as ViewHolder;
if (viewHolder.GroupCheckedTextView != null)
{
viewHolder.GroupCheckedTextView.Text = cursor.GetString(ColumnMapping["Name"]);
}
if (viewHolder.FieldTextView != null)
{
viewHolder.FieldTextView.Text = cursor.GetString(ColumnMapping["Value"]);
viewHolder.LabelTextView.Text = cursor.GetString(ColumnMapping["Label"]) ?? cursor.GetString(ColumnMapping["TypeLabel"]);
}
// I tried updating it manually, but it doesn't stick...
//viewHolder.GroupId = cursor.GetInt(ColumnMapping["GroupId"]);
//view.Tag = viewHolder;
}
public override View NewView(Context context, ICursor cursor, ViewGroup parent)
{
var inflator = LayoutInflater.FromContext(context);
View view = null;
if (IsNewGroup(cursor, cursor.Position))
{
view = inflator.Inflate(Resource.Layout.Group, parent, false);
}
else
{
view = inflator.Inflate(Resource.Layout.Field, parent, false);
}
var viewHolder = new ViewHolder(view);
viewHolder.GroupId = cursor.GetInt(ColumnMapping["GroupId"]);
view.Tag = viewHolder;
return view;
}
I think I understand why. The ViewHolder pattern is more about reusing the Views so you don’t have to search for them again, but is there any way to extend it to work with what I want? The only solution I can think of is to create a hidden view and stuff this integer into it’s text field, which I can retrieve later, but I hoping there is a less hacky solution.
That is correct, the holder patter is used to cache looking for views each time a row needs to be shown. Maybe I didn’t understand what you’re trying to do, but following:
Why can’t you simple get a reference to the underlining
Cursor(aCursorAdapterhas thegetCursormethod), step over it and extract the values you want(which, after reading your code, seems to be theidof the row)? You could always store internally, in the adapter, an array/list of the desired values from cursor. This array/list will be updated in thebindViewso you have the correct values in it.