My adapter not update correctly my listview option

I have the next problem. When I delete an item from my ListView in my adapter the state of the CheckBox change from item in list, Why? and, how can solve this problem?

public class CustomAdapter extends ArrayAdapter<RowModel> implements View.OnClickListener {

private ArrayList<RowModel> DataSet;
Context context;

public CustomAdapter(ArrayList<RowModel> data, Context context) {
    super(context, R.layout.list_item_main, data);
    this.DataSet = data;
    this.context = context;
}

@Override
public void onClick(View v) {
    int position = (Integer) v.getTag();
    Object object = getItem(position);
    RowModel dataRowModel = (RowModel) object;

    switch (v.getId()) {
        case R.id.list_checkbox:
            CheckBox checkBox = v.findViewById(R.id.list_checkbox);
            int bool = (checkBox.isChecked()) ? 1 : 0;
            new ListFacade(context).UpdateState(dataRowModel.getRowid(), bool);
            break;
        case R.id.list_delete_button:
            new ListFacade(context).DeleteRow(dataRowModel.getRowid());
            DataSet.remove(object);
            break;
    }
    notifyDataSetChanged();
    updateWidgetToChange();
}

if I delete the item 4

enter image description here

the checkbox of item 5 happens to be selected by the deletion of item 4

enter image description here

EDIT 1: added getView

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // Get the data item for this position
    RowModel dataRowModel = getItem(position);
    // Check if an existing view is being reused, otherwise inflate the view
    ViewHolder viewHolder; // view lookup cache stored in tag

    if (convertView == null) {
        viewHolder = new ViewHolder();
        LayoutInflater inflater = LayoutInflater.from(getContext());
        convertView = inflater.inflate(R.layout.list_item_main, parent, false);
        viewHolder.checkbox = convertView.findViewById(R.id.list_checkbox);
        viewHolder.checkbox.setChecked(dataRowModel.isChecked());
        viewHolder.title = convertView.findViewById(R.id.list_title);
        viewHolder.classes = convertView.findViewById(R.id.list_classes);
        viewHolder.rowid = convertView.findViewById(R.id.list_rowid);
        viewHolder.delete_button = convertView.findViewById(R.id.list_delete_button);

        convertView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }

    viewHolder.rowid.setText(dataRowModel.getStringRowid());
    viewHolder.title.setText(dataRowModel.getAction());
    viewHolder.classes.setText(dataRowModel.getType());
    viewHolder.checkbox.setOnClickListener(this);
    viewHolder.checkbox.setTag(position);
    viewHolder.delete_button.setOnClickListener(this);
    viewHolder.delete_button.setTag(position);
    // Return the completed view to render on screen
    return convertView;
}

Edit 2: Added ListFacade

public void UpdateState(int rowid, int bool){
    SQLiteDatabase conn = new SqliteHandler(context).getWritableDatabase();
    String strSQL = "UPDATE TODO_LIST SET CHECKED='"+ bool +"' WHERE ROWID = "+ rowid;
    conn.execSQL(strSQL);
    conn.close();
}

public void DeleteRow(int rowid){
    SQLiteDatabase conn = new SqliteHandler(context).getWritableDatabase();
    conn.delete("TODO_LIST", "ROWID=?", new String[]{String.valueOf(rowid)});
    conn.close();
}

Upvotes: 1

Views: 37

Answers (2)

jguerinet
jguerinet

Reputation: 1539

To add to @vilpe89's answer, the problem isn't that you aren't calling setChecked() in getView(), it's that you're calling it in the wrong spot:

viewHolder.checkbox.setChecked(dataRowModel.isChecked());

You call this line only if convertView == null, except that when you update the list convertView will not be null. Therefore, to fix your problem, you need to move that line to after the if else statement, like so:

viewHolder.checkbox.setOnClickListener(this);
viewHolder.checkbox.setChecked(dataRowModel.isChecked());
viewHolder.checkbox.setTag(position);

Upvotes: 0

vilpe89
vilpe89

Reputation: 4702

Just guessing but I think that you need to get the check box's state updated in getView-method. When you remove the object from dataSet, you need to make sure the isChecked is updated in the getView-method. Now when you remove the one data from dataSet and the list items are updated, the CheckBox's state is not changed.

Do you have something like this in your code?:

@Override
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
    // Other code...
    RowModel model = getItem(position);
    CheckBox cb = (CheckBox) convertView.findViewById(R.id.list_checkbox);
    cb.setChecked(model.isChecked());
    // ...
}

Because I'm seeing that you are not updating the dataset in your CheckBox's click listener.

So you need to add this in there also, or something like this:

case R.id.list_checkbox:
        CheckBox checkBox = v.findViewById(R.id.list_checkbox);
        dataRowModel.isChecked(checkBox.isChecked());
        // ... rest of the code

Edit:

The problem is that you are only updating the CheckBox when the View (convertView) is null! You need to move that code away from the if (convertView == null) because it gets only called when the View is created and when you call notifyDataSetChanged, the Views are not created again and your if-block is not reached.

Upvotes: 3

Related Questions