androidlistviewandroid-listviewmergecursor

listview setItemChecked not working properly


I am having an issue with a listview populated by a merge cursor. I have a button in my application to select all the entries in my listview. The function called when the button is pressed is the following:

private void selectAllEntries() {
    int numberOfItemsInList = listView.getCount();
    for (int i = 0; i < numberOfItemsInList; i++) {
        this.listView.setItemChecked(i, true);
    }
}

The problem is that not all the entries get checked in the end. Very weird indeed. After some testing I noticed that if I have 10 entries in the mergecursor (5 from cursor a and 5 from cursor b), then if I only use setItemChecked on the first 5 elements everything works okay (those 5 entries get checked). If I use setItemchecked on the last 5 elements again everything works okay (the entries from cursor b get checked), but if I use setItemChecked on elements from both cursors then the maximum number of elements getting checked is the number of elements in cursor a (5 in our example), with an offset of (number of items I wanted to set - number of items in cursor a). I'll write down a couple of examples as this is a very weird behaviour.

Example 1:
element 0 (from cursor a, unchecked)
element 1 (from cursor a, unchecked)
element 2 (from cursor a, unchecked)
element 3 (from cursor a, unchecked)
element 4 (from cursor a, unchecked)
element 5 (from cursor b, unchecked)
element 6 (from cursor b, unchecked) 
element 7 (from cursor b, unchecked)
element 8 (from cursor b, unchecked)
element 9 (from cursor b, unchecked)

setItemChecked(0,true);
setItemChecked(1,true);
setItemChecked(2,true);
setItemChecked(3,true);
setItemChecked(4,true);

Results:

element 0 (from cursor a, checked)
element 1 (from cursor a, checked)
element 2 (from cursor a, checked)
element 3 (from cursor a, checked)
element 4 (from cursor a, checked)
element 5 (from cursor b, unchecked)
element 6 (from cursor b, unchecked) 
element 7 (from cursor b, unchecked)
element 8 (from cursor b, unchecked)
element 9 (from cursor b, unchecked)

Example 2:
element 0 (from cursor a, unchecked)
element 1 (from cursor a, unchecked)
element 2 (from cursor a, unchecked)
element 3 (from cursor a, unchecked)
element 4 (from cursor a, unchecked)
element 5 (from cursor b, unchecked)
element 6 (from cursor b, unchecked) 
element 7 (from cursor b, unchecked)
element 8 (from cursor b, unchecked)
element 9 (from cursor b, unchecked)

setItemChecked(5,true);
setItemChecked(6,true);
setItemChecked(7,true);
setItemChecked(8,true);
setItemChecked(9,true);

results:

element 0 (from cursor a, unchecked)
element 1 (from cursor a, unchecked)
element 2 (from cursor a, unchecked)
element 3 (from cursor a, unchecked)
element 4 (from cursor a, unchecked)
element 5 (from cursor b, checked)
element 6 (from cursor b, checked) 
element 7 (from cursor b, checked)
element 8 (from cursor b, checked)
element 9 (from cursor b, checked)

Example 3:
element 0 (from cursor a, unchecked)
element 1 (from cursor a, unchecked)
element 2 (from cursor a, unchecked)
element 3 (from cursor a, unchecked)
element 4 (from cursor a, unchecked)
element 5 (from cursor b, unchecked)
element 6 (from cursor b, unchecked) 
element 7 (from cursor b, unchecked)
element 8 (from cursor b, unchecked)
element 9 (from cursor b, unchecked)

setItemChecked(0,true);
setItemChecked(1,true);
setItemChecked(2,true);
setItemChecked(3,true);
setItemChecked(4,true);
setItemChecked(5,true);

results in

element 0 (from cursor a, unchecked)
element 1 (from cursor a, checked)
element 2 (from cursor a, checked)
element 3 (from cursor a, checked)
element 4 (from cursor a, checked)
element 5 (from cursor b, checked)
element 6 (from cursor b, unchecked) 
element 7 (from cursor b, unchecked)
element 8 (from cursor b, unchecked)
element 9 (from cursor b, unchecked)


Example 4:
element 0 (from cursor a, unchecked)
element 1 (from cursor a, unchecked)
element 2 (from cursor a, unchecked)
element 3 (from cursor a, unchecked)
element 4 (from cursor a, unchecked)
element 5 (from cursor b, unchecked)
element 6 (from cursor b, unchecked) 
element 7 (from cursor b, unchecked)
element 8 (from cursor b, unchecked)
element 9 (from cursor b, unchecked)

setItemChecked(0,true);
setItemChecked(1,true);
setItemChecked(2,true);
setItemChecked(3,true);
setItemChecked(4,true);
setItemChecked(5,true);
setItemChecked(6,true);

results:

element 0 (from cursor a, unchecked)
element 1 (from cursor a, unchecked)
element 2 (from cursor a, checked)
element 3 (from cursor a, checked)
element 4 (from cursor a, checked)
element 5 (from cursor b, checked)
element 6 (from cursor b, checked) 
element 7 (from cursor b, unchecked)
element 8 (from cursor b, unchecked)
element 9 (from cursor b, unchecked)


Example 5:
element 0 (from cursor a, unchecked)
element 1 (from cursor a, unchecked)
element 2 (from cursor a, unchecked)
element 3 (from cursor a, unchecked)
element 4 (from cursor a, unchecked)
element 5 (from cursor b, unchecked)
element 6 (from cursor b, unchecked) 
element 7 (from cursor b, unchecked)
element 8 (from cursor b, unchecked)
element 9 (from cursor b, unchecked)

setItemChecked(0,true);
setItemChecked(1,true);
setItemChecked(2,true);
setItemChecked(3,true);
setItemChecked(4,true);
setItemChecked(5,true);
setItemChecked(6,true);
setItemChecked(7,true);

results:

element 0 (from cursor a, unchecked)
element 1 (from cursor a, unchecked)
element 2 (from cursor a, unchecked)
element 3 (from cursor a, checked)
element 4 (from cursor a, checked)
element 5 (from cursor b, checked)
element 6 (from cursor b, checked) 
element 7 (from cursor b, checked)
element 8 (from cursor b, unchecked)
element 9 (from cursor b, unchecked)

I am using the

        listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

and

notifyDataSetChanged()

doesn't help either. Any help ?

As a side-note, the

listView.getCount();

always returns the correct number of entries in the view


Solution

  • as alanv said, "CursorAdapter uses the _id column from your database to identify rows, and AbsListView uses this value to keep track of which rows are checked. It sounds like your MergeCursor may be returning duplicate IDs, e.g the _id value for the first row in cursor A is identical to the _id for the first row in cursor B. Is that the case?"

    that is exactly the case. After changing the cursor to provide different Ids it all works okay However:

    1. A merge cursor is a concatenation of other cursors, shouldn't the merge cursor be able to handle with identical ids coming from different sub-cursors (e.g. by creating new id's internally).
    2. Viewing all the results of the merge cursor,and interacting with them (clicking them) works okay, so I would expect checking them to work properly as well as it is?