I am developing an android application which uses a ListView to display users and their profiles. You can see on the picture below, how it actually looks. It is possible to have large amount of users, so I implemented lazy loading feature which loads four users in a round. When the application starts (4 users in the list), everything looks great but after I scroll down and load next four users, something strange happens. As you can see on the image, every user has his pawn and for instance some of them have glasses and some of them not. After scrolling it appears that the newly loaded users or some of them also have glasses, although they shouldn't have them.
http://pasteboard.co/1xs78l6C.png
I can guess that the problem happens because the adapter recycles the views. The views consist of many images and I think that implementing the adapter without this feature (recycling) wouldn't be a great idea. On the other hand I am not well experienced with it and I don't know where I should pay attention to prevent this behavior. I'll appreciate any help or suggestions how to fix this issue.
here you can see how my adapter looks like
public class UserAdapter extends BaseAdapter {
private final Context context;
private ArrayList<User> users;
private HashMap<String, Integer> resIds;
private final int[] slotIds = { R.id.imgRowSlot1, R.id.imgRowSlot2,
R.id.imgRowSlot3 };
public UserAdapter(Context context) {
this.context = context;
users = new ArrayList<User>();
resIds = new HashMap<String, Integer>(Config.init());
}
public void updateUsers(List<User> users) {
this.users = new ArrayList<User>(users);
notifyDataSetChanged();
}
@Override
public int getCount() {
return users.size();
}
@Override
public User getItem(int position) {
return users.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView txtFirstName;
TextView txtLastName;
ImageView imgSlot1;
ImageView imgSlot2;
ImageView imgSlot3;
ImageView imgHead;
ImageView imgGlasses;
ImageView imgTop;
ImageView imgBottom;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(
R.layout.user_row, parent, false);
txtFirstName = (TextView) convertView
.findViewById(R.id.txtFirstName);
txtLastName = (TextView) convertView.findViewById(R.id.txtLastName);
imgSlot1 = (ImageView) convertView.findViewById(R.id.imgRowSlot1);
imgSlot2 = (ImageView) convertView.findViewById(R.id.imgRowSlot2);
imgSlot3 = (ImageView) convertView.findViewById(R.id.imgRowSlot3);
imgHead = (ImageView) convertView
.findViewById(R.id.imgHead_adapter);
imgGlasses = (ImageView) convertView
.findViewById(R.id.imgGlasses_adapter);
imgTop = (ImageView) convertView.findViewById(R.id.imgTop_adapter);
imgBottom = (ImageView) convertView
.findViewById(R.id.imgBottom_adapter);
convertView.setTag(new ViewHolder(txtFirstName, txtLastName,
imgSlot1, imgSlot2, imgSlot3, imgHead, imgGlasses, imgTop,
imgBottom));
} else {
ViewHolder viewHolder = (ViewHolder) convertView.getTag();
txtFirstName = viewHolder.txtFirstName;
txtLastName = viewHolder.txtLastName;
imgSlot1 = viewHolder.imgSlot1;
imgSlot2 = viewHolder.imgSlot2;
imgSlot3 = viewHolder.imgSlot3;
imgHead = viewHolder.imgHead;
imgGlasses = viewHolder.imgGlasses;
imgTop = viewHolder.imgTop;
imgBottom = viewHolder.imgBottom;
}
User user = getItem(position);
int[] slots = user.getSlots();
// name
txtFirstName.setText(user.getFirstName());
txtLastName.setText(user.getLastName());
// fruits
imgSlot1.setImageResource(MyDataController.fruits[slots[0]]);
imgSlot2.setImageResource(MyDataController.fruits[slots[1]]);
imgSlot3.setImageResource(MyDataController.fruits[slots[2]]);
FruitExtractor.setAlpha(convertView, slotIds, user);
// pawn head
if (user.getConsCounter() >= 2) {
imgHead.setImageResource(R.drawable.head_happy_noeyes);
} else if (user.getConsCounter() == 1) {
imgHead.setImageResource(R.drawable.head_indiferent_noeyes);
} else {
imgHead.setImageResource(R.drawable.head_sad_noeyes);
}
// glasses
if (user.getGlasses() != null) {
imgGlasses.setImageResource(resIds.get(user.getGlasses()
.getResIdName()));
}
// body
imgTop.setImageResource(resIds.get(user.getTop().getResIdName()));
imgBottom.setImageResource(resIds.get(user.getBottom().getResIdName()));
return convertView;
}
private static class ViewHolder {
public final TextView txtFirstName;
public final TextView txtLastName;
public final ImageView imgSlot1;
public final ImageView imgSlot2;
public final ImageView imgSlot3;
public final ImageView imgHead;
public final ImageView imgGlasses;
public final ImageView imgTop;
public final ImageView imgBottom;
public ViewHolder(TextView txtFirstName, TextView txtLastName,
ImageView imgSlot1, ImageView imgSlot2, ImageView imgSlot3,
ImageView imgHead, ImageView imgGlasses, ImageView imgTop,
ImageView imgBottom) {
this.txtFirstName = txtFirstName;
this.txtLastName = txtLastName;
this.imgSlot1 = imgSlot1;
this.imgSlot2 = imgSlot2;
this.imgSlot3 = imgSlot3;
this.imgHead = imgHead;
this.imgGlasses = imgGlasses;
this.imgTop = imgTop;
this.imgBottom = imgBottom;
}
}
public List<User> getUsers() {
return users;
}
}
// glasses
if (user.getGlasses() != null) {
imgGlasses.setImageResource(resIds.get(user.getGlasses()
.getResIdName()));
}else{
//there is no else statement to clear the previous glasses
//you can do something like this
imgGlasses.setImageResource(android.R.color.transparent);
}