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

5

13

(Not specific to ListView, but to Adapter).

I keep implementing this when I subclass BaseAdapter:

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

Because have to implement that. I don't see any use of it, I need getItem(position) only, not getItemId(position).

I wonder if it has any significance (to Android SDK or something else)?

Fullerton answered 24/2, 2011 at 3:32 Comment(0)
S
4

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.

Stoffel answered 30/9, 2014 at 8:34 Comment(0)
D
32

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;
    }
}
Discipline answered 25/3, 2012 at 19:27 Comment(3)
Almost, but not quite... position and itemId are NOT the same in Array/SimpleAdapter if a header view is attached to the list! In these cases, use the row id instead of the position so you don't need to 'calculate' the actual item row from the list position.Nevis
@dhaval maybe because this answers what ids are but not what they are used for.Welcome
@dhaval Yes Simas's comment is correct. This answer explains what ids are but not why I must implement getItemId. Sometimes I don't use getItemId at all, since getItem usually returns an "item" that already contains the id.Pia
S
4

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.

Stoffel answered 30/9, 2014 at 8:34 Comment(0)
C
1

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.

Cloddish answered 26/3, 2012 at 15:37 Comment(0)
N
0

If you subclass ArrayAdapter instead, you may not have to implement that method.

Mostly I find that method useful to determine what row was clicked during onClick events, and use that ID as part of the Intent extras passed to the next activity.

Newspaper answered 23/7, 2011 at 15:58 Comment(0)
R
-1

Yes it is an abstract function which is called by android to map the adapter data-set row id to your list position.

You are welcome to dig deeper

Refusal answered 24/2, 2011 at 3:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.