Reputation: 157
Hello Stack Overflow Android Users,
Please help with the following question:
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:
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.
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
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
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