So I have a listview pulling data from a Room based SQLite database. It is reading the data just fine it seems, but when the page loads I will get the first ~10 entries (the size of the display), and when I attempt to scroll down on the listview it starts back over and begins getting the entries at the beginning of the list again. The red circles on the screenshot demonstrate the top and bottom of the list and the repetition that is present.
public class NeighborhoodListAdapter
extends ArrayAdapter<LivingCity> {
private List<LivingCity> neighborhood;
Context context;
// View lookup cache
private static class ViewHolder {
TextView cityName;
}
public NeighborhoodListAdapter(List<LivingCity> neighborhood, Context context) {
super(context, R.layout.object_main_citydetailsrow, neighborhood);
this.context = context;
this.neighborhood = neighborhood;
}
@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
LivingCity city = getItem(position);
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.object_main_citydetailsrow, parent, false);
viewHolder.cityUid = (TextView) convertView.findViewById(R.id.cityrow_uid);
viewHolder.cityUid.setText(String.format(Locale.ENGLISH,"#%d", city.getUid()));
}//city.getUid() returns an int
}catch (Exception e){
Log.d("editCity: ", e.toString());
}
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
// Return the completed view to render on screen
return convertView;
}
}
and I am starting it with
void loadNeighborhood() {
neighborhoodDB = Neighborhood.getAppDatabase(this);
neighborhood = neighborhoodDB.getNeighborhood();
}
which pulls a sorted list from the database helper
public List<LivingCity> getNeighborhood() {
List<LivingCity> neighborhood = cityDao().getAll();
Collections.sort(neighborhood,
new Comparator<LivingCity>() {
@Override
public int compare(LivingCity city1, LivingCity city2) {
return Integer.valueOf(city1.getUid()).compareTo(city2.getUid());
} //I thought this sort operation might be whats wrong but same error with it commented out
});
return neighborhood;
}
Edit: Additionally, if I scroll to the bottom repeatedly without going up I can trick it into shuffling some of the upper items as shown in the screenshot (Orange).
When you scroll the ListView
recycles old views. But you are only updating the value only when a new row is inflated. Inflation of a new row does not occur all the time, it reuses an old row. This this the reason you are seeing old values again.
Move the line viewHolder.cityUid.setText();
below the if-else
block as below.
@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
LivingCity city = getItem(position);
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.object_main_citydetailsrow, parent, false);
viewHolder.cityUid = (TextView) convertView.findViewById(R.id.cityrow_uid);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
//city.getUid() returns an int
viewHolder.cityUid.setText(String.format(Locale.ENGLISH,"#%d", city.getUid()));
// Return the completed view to render on screen
return convertView;
}