CheckBox gets unchecked on scroll in a custom listview

Here is an example. Read the comments in the getView(...) of the adapter provided below.


class TaskObject {
        private int pid;
        private String processName;
        private boolean toKill;
///getters/setters
        public boolean isToKill() {
            return toKill;
        }    
        public void setToKill(boolean toKill) {
            this.toKill = toKill;
        }
       ................................
    }

class TaskListAdapter extends BaseAdapter {

    private static final String TAG = "adapter";

    ArrayList<TaskObject> list;
    Context context;

    public TaskListAdapter(Context context) {
        Log.d(TAG, "created new task list adapter");
        this.context = context;
        if (list == null) {
            list = new ArrayList<TaskObject>();
        }
    }

    public void addTask(TaskObject taskObject) {
        list.add(taskObject);
    }

    public void clearTasks() {
        list.clear();
        Log.d(TAG, "list size:" + list.size());
        this.notifyDataSetChanged();
    }

    public int getCount() {
        return list.size();
    }

    public TaskObject getItem(int position) {
        return list.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(final int position, View convertView, ViewGroup parent) {        
        RelativeLayout rl = new RelativeLayout(context);
        TextView textPid = new TextView(context);
        textPid.setText(Integer.toString(getItem(position).getPid()));
        TextView textName = new TextView(context);
        textName.setText(getItem(position).getProcessName()); 

       /////Here is your and it will set back your checked item after scroll
         CheckBox chckKill = new CheckBox(context);
            if(getItem(position).isToKill())
            {
                    chckKill.setChecked(true);
            }
       ////////////////////////////////////////////////////////////////////           

            chckKill.setOnClickListener(new View.OnClickListener() {
              public void onClick(View v) {
                //is chkIos checked?
             if (((CheckBox) v).isChecked()) {
                 getItem(position).setToKill(true);
                }
              }
            });
            chckKill.setTag(getItem(position).getPid());
        /////////NOT LAYOUTED USE LAYOUT
            rl.addView(chckKill);
            rl.addView(textName);
            rl.addView(textPid);
            return rl;
        }    

hope it helps abit.


getView() is called whenever a previously invisible list item needs to be drawn. Since you recreate itemChecked[] each time this method is called you will have the new checkbox unchecked and a different Array for each resulting View. (final in Java does not make that field unique like in C) Simplest way to solve that is to make itemChecked a classmember and set / restore checkbox state based on that one.

public class MyListAdapter extends ArrayAdapter<Object> {
    private final boolean[] mCheckedState;
    private final Context mContext;

    public MyListAdapter(Context context, int resource, int textViewResourceId, List<Object> objects) {
        super(context, resource, textViewResourceId, objects);
        mCheckedState = new boolean[objects.size()];
        mContext = context;
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // simplified to just a Checkbox
        // ViewHolder and OnCheckedChangeListener stuff left out 
        CheckBox result = (CheckBox)convertView;
        if (result == null) {
            result = new CheckBox(mContext);
        }
        result.setChecked(mCheckedState[position]);
        return result;
    }
}