What's the purpose of item-id's in Android ListView Adapter?

Imagine this structure:

You have db table Notes with such 3 records:

+----+--------------------------+
| ID | Note Text                |
+----+--------------------------+
| 43 | Note text blah blah      |
| 67 | Note text blah blah blah |
| 85 | Last note                |
+----+--------------------------+

and you implement an adapter to serve this data.

Now let's see what position and item id are in such a case

position - is an ordinal number of record position in the loaded dataset. For example if you load that table with ORDER BY ID ASC, then

  • record with ID 43 will have position 0,
  • record with ID 67 will have position 1,
  • record with ID 85 will have position 2

itemId - is a "primary key" of a record, and your implementation can return such values

  • record with ID 43 should have itemId 43,
  • record with ID 67 should have itemId 67,
  • record with ID 85 should have itemId 85

position and itemId in Android standard adapters

ArrayAdapter / SimpleAdapter

In ArrayAdapter and SimpleAdapter position and itemId is the same thing:

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

SimpleCursorAdapter (and all types that inherit from CursorAdapter)

In the SimpleCursorAdapter and all descendants of CursorAdapter itemId is a value from _id column:

public long getItemId(int position) {
    if (mDataValid && mCursor != null) {
        if (mCursor.moveToPosition(position)) {
            return mCursor.getLong(mRowIDColumn);
        } else {
            return 0;
        }
    } else {
        return 0;
    }
}

There are probably many reasons to have stable item IDs. A default implementation cannot be given since it depends on the type of Object being stored in the Adapter.

Android has a check to make sure that item IDs are used only when they are stabled, i.e. the subclass has properly overridden getItemId; BaseAdapter.hasStableIds must be overriden to return true.

Few reasons I have come across:

  • AdapterView.OnItemClickListener's method onItemClick(AdapterView<?> parent, View view, int position, long id) also sends long id

  • the getCheckedItemIds method The result is only valid if the choice mode has not been set to CHOICE_MODE_NONE and the adapter has stable IDs.

Reply to "Because have to implement that": you don't have to If you don't use the features, there's no need. But if you do, don't forget to override boolean hasStableIds() as well.


As @Reno writes, it allows you to map rows in the view to data-set elements.

One of the purposes of this is to allow ListViews to keep track of which item is selected, even if the positions in the list are changed or the underlying data is updated.