TeamChillshot
TeamChillshot

Reputation: 157

Custom ListView Adapter Showing Incorrect Values [Mono Android]

Hello Stack Overflow Android Users,

Please help with the following question:

Problem

I'm writing an a feature for an app that lists species of fish. I'm using a custom ListView Adapter class (let's call this FishSpeciesListAdapter) for the adapter. I have 27 fish species recorded as a default for the program as for now (you will eventually be able to add some yourself as well). The problem is that when I link the adapter to the actual listview xml object, it seems to iterate over the same 5-6 species all the time.

The problem must lie within the custom adapter because I've tested the recorded species and all species are different within a List that I pass to the adapter.

Here's the code where I set the adapter:

this.n_fishSpeciesListView = FindViewById<ListView> (Resource.Id.xml_fishSpeciesListView);
this.n_fishSpeciesListView.Adapter = new FishSpeciesListAdapter (this, 
this.n_model.SpecieManager.Species);

Here's the Custom ListView Adapter code:

public class FishSpeciesListAdapter : BaseAdapter
{
    Context n_context;
    List<AppCode.Specie> n_specieData;

    public FishSpeciesListAdapter (Context context, List<AppCode.Specie> specieData)
    {
        this.n_context = context;
        this.n_specieData = specieData;
    }

    public override int Count {
        get { return this.n_specieData.Count; }
    }

    public override Java.Lang.Object GetItem (int position)
    {
        return null;
    }

    public override long GetItemId (int position)
    {
        return 0;
    }

    // create a new ImageView for each item referenced by the Adapter
    public override View GetView (int position, View convertView, ViewGroup parent)
    {
        View v;
        if(convertView==null){

            LayoutInflater li = LayoutInflater.FromContext(parent.Context);
            v = li.Inflate(Resource.Layout.Adapter_FishSpeciesIcon, null);
            ImageView iconImage = (ImageView)v.FindViewById(Resource.Id.xml_adapter_fishSpeciesIconImage);
            TextView nameText = (TextView)v.FindViewById(Resource.Id.xml_adapter_fishSpeciesNameText);
            TextView scientificNameText = (TextView)v.FindViewById(Resource.Id.xml_adapter_fishSpeciesScientificNameText);

            nameText.Text = this.n_specieData[position].Name;
            scientificNameText.Text = this.n_specieData[position].ScientificName;

            if (this.n_specieData[position].RelatedMedia.AttachedPhotos.Count < 1)
            {
                iconImage.SetImageResource(Resource.Drawable.Icon); 
            }
            else
            {
                iconImage.SetImageBitmap(BitmapFactory.DecodeByteArray(this.n_specieData[position].RelatedMedia.AttachedPhotos[0], 0, this.n_specieData[position].RelatedMedia.AttachedPhotos[0].Length));  
            }   
        }
        else
        {
            v = convertView;
        }
        return v;
    }
}

So when I execute the above code, here's a screenshot of what I get:

Items Repeat themselves when there should be 27 unique species here, of course this isnt the whole list but an example where you can see the looping happen!

As you can see there are duplicates where I'm am positive that there are at least 27 different species recorded in the passed List variable. Any help as to why this is and how I can fix this would be very helpful.

My Research

I've read that it may be reusing the "View currentView" variable in the GetView method of the adapter. I found that information out in this link. I just don't know how to fix this in my case. Code examples would be nice or detailed directions. Thank you for your time.

Upvotes: 1

Views: 2663

Answers (2)

Anand Sriraman
Anand Sriraman

Reputation: 168

From what I see, you're using the convertView object wrong. This object is available in case any Views have been recycled (for example a list item scrolled out of view). It is available so that you don't have to inflate from your layout xml again (which is a costly process).

What you should do is inflate from your layout xml if convertView==null. Otherwise use the convertView object.

 if(convertView==null){

        LayoutInflater li = LayoutInflater.FromContext(parent.Context);
        v = li.Inflate(Resource.Layout.Adapter_FishSpeciesIcon, null);
}
else{
     v=convertView;
}

Then use v to set all your values and return the View.

    ImageView iconImage = (ImageView)v.FindViewById(Resource.Id.xml_adapter_fishSpeciesIconImage);
        TextView nameText = (TextView)v.FindViewById(Resource.Id.xml_adapter_fishSpeciesNameText);
        TextView scientificNameText = (TextView)v.FindViewById(Resource.Id.xml_adapter_fishSpeciesScientificNameText);

 nameText.Text = this.n_specieData[position].Name;
 scientificNameText.Text = this.n_specieData[position].ScientificName;

 if (this.n_specieData[position].RelatedMedia.AttachedPhotos.Count < 1)
 {
       iconImage.SetImageResource(Resource.Drawable.Icon); 
 }
 else
 {
       iconImage.SetImageBitmap(BitmapFactory.DecodeByteArray(this.n_specieData[position].RelatedMedia.AttachedPhotos[0], 0, this.n_specieData[position].RelatedMedia.AttachedPhotos[0].Length));  
 }   
 return v;

Upvotes: 1

elgui
elgui

Reputation: 3323

you need to reuse convertView when it already exists, or create a new view when it doesn't. In all cases, you have to give your textViews/imageViews the right properties :

public override View GetView (int position, View convertView, ViewGroup parent)
{
    if(convertView==null){

        LayoutInflater li = LayoutInflater.FromContext(parent.Context);
        convertView = li.Inflate(Resource.Layout.Adapter_FishSpeciesIcon, null);
    }
    ImageView iconImage = (ImageView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesIconImage);
    TextView nameText = (TextView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesNameText);
    TextView scientificNameText = (TextView)convertView.FindViewById(Resource.Id.xml_adapter_fishSpeciesScientificNameText);

    nameText.Text = this.n_specieData[position].Name;
    scientificNameText.Text = this.n_specieData[position].ScientificName;

    if (this.n_specieData[position].RelatedMedia.AttachedPhotos.Count < 1)
    {
        iconImage.SetImageResource(Resource.Drawable.Icon); 
    }
    else
    {
        iconImage.SetImageBitmap(BitmapFactory.DecodeByteArray(this.n_specieData[position].RelatedMedia.AttachedPhotos[0], 0, this.n_specieData[position].RelatedMedia.AttachedPhotos[0].Length));  
    }   
    }

    return convertView;
}

Upvotes: 1

Related Questions