Juri Strumpflohner
Juri Strumpflohner Juri is a full stack developer and tech lead with a special passion for the web and frontend development. He creates online videos for Egghead.io, writes articles on his blog and for tech magazines, speaks at conferences and holds training workshops. Juri is also a recognized Google Developer Expert in Web Technologies

Retrieve Selected Items on Checkable ListView: Differences in SDK Level 7 and 8

2 min read

I'm currently testing my Android app that I'm developing for my MSc thesis on different real devices. While I own a Nexus One with Android Froyo 2.2 installed (SDK Level 8) I got now another device, an HTC Hero with a slightly older version, namely v2.1-update1 (Level 7).

And while doing some tests I observed an interesting behavior when working with checkable ListViews, basically those where you set the "choice mode" to ListView.Choice_MODE_MULTIPLE. I use this for giving the possibility to tag some items. The user gets a list of available tags on which he can select multiple ones and once he closes the activity, I collect the selected items and update the underlying data accordingly.



On SDK Level 8, what you would do is to call the getCheckedItemIds() which returns an array of type long[] containing all of the ids of the selected tags.
long[] selectedIds = getListView().getCheckedItemIds();
This is really handy since you can now just call your DB access layer and update your data with the given ids. Sadly this method is not supported on SDK level 7. So if you need to be backward compatible you better don't use this method, but instead there is apparently a similar one, getCheckItemIds() (I thought). However, using it resulted in strange side effects. It seemed as if not only the active items but also those which were active at startup of the dialog but which have then become inactive later due to the user's interaction. In fact, looking at the new API level 8 ListView method you'll find it to be depreciated with a comment
Old behavior was buggy, but would sort of work for adapters without stable IDs.
Fall back to it to support legacy apps.
Having stable ids, it didn't work for me, so I coded the solution myself:
private long[] getCheckedItemsIdsFix(){
SparseBooleanArray checkItemPositions = getListView().getCheckedItemPositions();
int checkedPositionsCount = checkItemPositions.size();

long[] checkedIds = new long[checkedPositionsCount];
int checkedCount = 0;
for (int i = 0; i < checkedPositionsCount; i++) {
if(checkItemPositions.valueAt(i)){
checkedIds[checkedCount++] = getListAdapter().getItemId(checkItemPositions.keyAt(i));
}
}

//check whether the size matches, otherwise shrink the array.
if(checkedCount == checkedPositionsCount)
return checkedIds;
else{
final long[] adjustedIdsArray = new long[checkedCount];
System.arraycopy(checkedIds, 0, adjustedIdsArray, 0, checkedCount);

return adjustedIdsArray;
}
}

Questions? Thoughts? Hit me up on Twitter
comments powered by Disqus