This is regarding the recycling issue. I am using a custom adapter to populate the list view. In the custom row there is an image view, two text boxes and a check box. The all the elements get populated but the check box is not populated correctly.
Inside the getView()
I perform a condition and if the condition is true I set the check box to enable state. This works fine but with the correct check box which is ticked, there are some other check boxes getting ticked as well. I went through many stack overflow similar questions but was unable to find an answer. Any help is greatly appreciated.
Below is my adapter class:
public class LocationsListAdapter extends BaseAdapter {
List<Locations> data;
Context context;
Locations userSelectedLocation;
private SharedPreferences locationPreferences;
private SharedPreferences.Editor locationPrefsEditor;
public LocationsListAdapter(List<Locations> data, Context c) {
this.data = data;
this.context = c;
}
@Override
public int getCount() {
return data.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return data.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@SuppressWarnings("static-access")
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
Log.v("ConvertView", String.valueOf(position));
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = vi.inflate(R.layout.find_your_location_row, null);
holder = new ViewHolder();
holder.LocationImage = (SmartImageView) convertView.findViewById(R.id.loca_row_image);
holder.locationName = (TextView) convertView.findViewById(R.id.txt_loca_name);
holder.LocationDescription = (TextView) convertView.findViewById(R.id.txt_loca_desc);
holder.locationCheckText = (TextView) convertView.findViewById(R.id.txt_check);
holder.locationCheck = (CheckBox) convertView.findViewById(R.id.location_check);
holder.locationCheck.setOnCheckedChangeListener(myCheckChangList);
convertView.setTag(holder);
locationPreferences = context.getSharedPreferences("locationPrefs", context.MODE_PRIVATE);
locationPrefsEditor = locationPreferences.edit();
String locationID = locationPreferences.getString("locationID", "");
try {
if(locationID.contains(String.valueOf(data.get(position).getLocationID()))){
holder.locationCheck.setChecked(true);
}
} catch (Exception e) {
Log.e("Fatal", " Exception");
}
holder.locationCheck.setOnClickListener( new OnClickListener() {
@Override
public void onClick(View v) {
userSelectedLocation = data.get(position);
locationPreferences = context.getSharedPreferences("locationPrefs", context.MODE_PRIVATE);
locationPrefsEditor = locationPreferences.edit();
String userSelectedLocationID = userSelectedLocation.getLocationID();
locationPrefsEditor.clear();
locationPrefsEditor.putString("locationID", userSelectedLocationID);
locationPrefsEditor.commit();
Intent intent = new Intent(context, HomeScreen.class);
context.startActivity(intent);
Log.e("Check Box ", "Clicked");
}
});
}else {
holder = (ViewHolder) convertView.getTag();
}
final Locations location = data.get(position);
holder.LocationImage.setImageUrl(location.getImagePath());
holder.locationName.setText(location.getLocationName());
holder.LocationDescription.setText(location.getLocationDescription());
return convertView;
}
@Override
public void unregisterDataSetObserver(DataSetObserver observer) {
if (observer != null) {
super.unregisterDataSetObserver(observer);
}
}
protected class ViewHolder {
protected SmartImageView LocationImage;
protected TextView locationName;
protected TextView LocationDescription;
protected TextView locationCheckText;
protected CheckBox locationCheck ;
}
OnCheckedChangeListener myCheckChangList = new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
Log.e("checked", "");
}
};
}
I believe your problem lies in your if/else statement.
If convertView is null then you create a new view and populate it with all the correct data but if it is not null (i.e it is a recycled view), you simply return the exact same view back from the tag. You do not do anything with the view regarding setting its properties so it maintains the state it already had (some of which were checked)
Set your properties after you have a valid viewHolder.
You currently have this model.
Change it to this (move the code that sets the view properties outside the if/else so that the view properties can be set for all views regardless of whether they are recycled.