What's the purpose of item-id's in Android

2019-01-06 19:53发布

问题:

(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)?

回答1:

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.



回答2:

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;
    }
}


回答3:

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.



回答4:

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.



回答5:

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