Какова цель методов getItem и getItemId в базовом адаптере Android?
Мне интересно узнать о целях методов getItem и getItemId в класса в Android SDK.
Из описания, кажется, что getItem должен вернуть базовые данные. Итак, если у меня есть массив имен [ "cat", "dog", "red" ], и я создаю адаптер, используя это, тогда a.getItem(1) должен возвращать "собаку", правильно? Что должно вернуть a.getItemId(1)?
Если вы использовали эти методы на практике, не могли бы вы привести пример?
Ответы
Ответ 1
Я рассматриваю эти методы как более чистый подход к доступу к моим данным списка. Вместо прямого доступа к объекту адаптера через myListData.get(position)
я могу просто вызвать адаптер, например adapter.get(position)
.
То же самое относится к getItemId
. Обычно я использую этот метод, когда хочу выполнить некоторую задачу на основе уникального идентификатора объекта в списке. Это особенно полезно при работе с базой данных. Возвращенный id
может быть ссылкой на объект в базе данных, который затем я мог выполнять различные операции (update/delete/etc).
Поэтому вместо доступа к идентификатору из необработанного объекта данных, например myListData.get(position).getId()
, вы можете использовать adapter.getItemId(position)
.
Один пример того, где я чувствовал, что мне нужно использовать эти методы, был в проекте с помощью SeparatedListViewAdapter. Этот адаптер может содержать несколько различных типов адаптеров, каждый из которых представляет данные другого типа (обычно). При вызове getItem(position)
на SeparatedListViewAdapter
возвращаемый объект может отличаться в зависимости от того, какой "раздел" является позицией, которую вы отправляете.
Например, если в вашем списке было 2 раздела (фрукты и конфеты): Если вы использовали getItem(position)
и position
, которые находились на элементе в разделе фрукты, вы бы получить другой объект, чем если бы вы запросили getItem(position)
с position
, указывающим на элемент в разделе конфеты. Затем вы можете вернуть какое-то постоянное значение ID в getItemId(position)
, которое представляет, какие данные getItem(position)
возвращаются, или использовать instanceof
, чтобы определить, какой у вас объект.
Помимо того, что я упомянул, я никогда не чувствовал, что мне действительно нужно использовать эти методы.
Ответ 2
Ну, похоже, на этот вопрос можно было ответить более простым и простым способом...: -)
Проще говоря, Android позволяет вам прикрепить long
к любому элементу ListView
, это просто. Когда система уведомляет вас о выборе пользователя, вы получаете три идентифицирующие переменные, чтобы сообщить вам, что было выбрано:
- ссылка на представление,
- его числовое положение в списке,
- это
long
, которое вы привязали к отдельным элементам.
Вам решать, какой из этих трех проще всего обрабатывать в вашем конкретном случае, но у вас есть все трое, чтобы выбирать все время. Подумайте об этом long
как теге, автоматически прикрепленном к элементу, только чтобы он был еще проще и легче читать.
Непонимание о том, что он обычно делает, проистекает из простого соглашения. Все адаптеры должны предоставить getItemId()
, даже если они фактически не используют эту третью идентификацию. Итак, по соглашению, эти адаптеры (в том числе многие из образцов в SDK или во всем Интернете) просто возвращают position
по одной причине: он всегда уникален. Тем не менее, если адаптер возвращает position
, это действительно означает, что он вообще не хочет использовать эту функцию, поскольку position
уже известен.
Итак, если вам нужно вернуть любое другое значение, которое вам подходит, не стесняйтесь:
@Override
public long getItemId(int position) {
return data.get(position).Id;
}
Ответ 3
Метод getItemId
в основном предназначен для работы с курсорами, которые поддерживаются базами данных SQLite. Он вернет исходное поле идентификатора курсора для элемента в позиции 1.
В вашем случае нет идентификатора для элемента в позиции 1: я предполагаю, что реализация ArrayAdapter возвращает -1 или 0.
EDIT: на самом деле он просто возвращает позицию: в этом случае 1
.
Ответ 4
Я хотел бы упомянуть, что после реализации getItem
и getItemId
вы можете использовать ListView.getItemAtPosition и ListView.getItemIdAtPosition, чтобы напрямую обращаться к вашим данным, вместо перехода через адаптер. Это может быть особенно полезно при реализации прослушивателя onClick.
Ответ 5
Если вы правильно реализуете getItemId
, тогда это может быть очень полезно.
Пример:
У вас есть список альбомов:
class Album{
String coverUrl;
String title;
}
И вы реализуете getItemId
следующим образом:
@Override
public long getItemId(int position){
Album album = mListOfAlbums.get(position);
return (album.coverUrl + album.title).hashcode();
}
Теперь ваш идентификатор элемента зависит от значений полей coverUrl и title, и если вы измените его и вызовите notifyDataSetChanged()
на свой адаптер, тогда адаптер вызовет getItemId() для каждого элемента и обновить только те элементы, которые изменили идентификатор.
Это очень полезно, если вы выполняете "тяжелые" операции в getView()
.
BTW: если вы хотите, чтобы это сработало, вам нужно убедиться, что ваш метод hasStableIds()
возвращает false;
Ответ 6
getItem
или getItemId
- это несколько методов, предназначенных главным образом для прикрепленных данных с элементами в списке. В случае getItem
вы можете передать любой объект, который будет прикрепляться к элементу в списке. Обычно люди возвращаются null
. getItemId
- любое уникальное значение long
, которое вы можете прикрепить с тем же элементом в списке. Люди обычно возвращают позицию в списке.
Какое использование. Ну, поскольку эти значения привязаны к элементу в списке, вы можете извлечь их, когда пользователь нажимает на элемент. Эти значения доступны с помощью методов AdapterView
.
// template class to create list item objects
class MyListItem{
public String name;
public long dbId;
public MyListItem(String name, long dbId){
this.name = name;
this.dbId = dbId;
}
}
///////////////////////////////////////////////////////////
// create ArrayList of MyListItem
ArrayList<MyListItem> myListItems = new ArrayList<MyListItem>(10);
// override BaseAdapter methods
@Override
public Object getItem(int position) {
// return actual object <MyListItem>
// which will be available with item in ListView
return myListItems.get(position);
}
@Override
public long getItemId(int position) {
// return id of database document object
return myListItems.get(position).dbId;
}
///////////////////////////////////////////////////////////
// on list item click, get name and database document id
my_list_view.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// extract item data
MyListItem selectedItem = (MyListItem)parent.getItemAtPosition(position);
System.out.println("Your name is : " + selectedItem.name);
// extract database ref id
long dbId = id;
// or you could also use
long dbId = parent.getItemIdAtPosition(position);
}
});