Answers:
我认为这些方法是访问列表数据的一种更干净的方法。无需通过类似的方式直接访问我的适配器对象,myListData.get(position)
只需调用类似的适配器即可adapter.get(position)
。
也是一样getItemId
。当我想基于列表中对象的唯一ID执行某些任务时,通常会使用此方法。在使用数据库时,这特别有用。返回的内容id
可能是对数据库中对象的引用,然后我可以对它执行不同的操作(更新/删除/等)。
因此,myListData.get(position).getId()
可以像使用一样从原始数据对象访问ID adapter.getItemId(position)
。
我感觉需要使用这些方法的一个示例是在使用SeparatedListViewAdapter的项目中。该适配器可以包含多种不同类型的适配器,每种适配器代表不同类型(通常)的数据。调用getItem(position)
时SeparatedListViewAdapter
,返回的对象可能会有所不同,具体取决于您发送该对象的位置是“节”。
例如,如果你有2个部分在列表中(水果和糖果):如果你使用getItem(position)
和position
碰巧在该项目的水果节,比如果你要求,你会收到一个不同的对象getItem(position)
与position
在指向一个项目的糖果部分。然后,您可能会返回某种常量ID值,getItemId(position)
该值表示getItem(position)
正在返回的数据类型,或者用于instanceof
确定您拥有的对象。
除了我刚才提到的以外,我从未觉得我真的需要使用这些方法
getView
,getCount
,getViewTypeCount
,等是专门为正常显示你的ListView UI使用。其他功能只是帮助创建其他功能,例如在单击某个项目时执行其他操作等。尽管我经常getItem
在内部使用getView
getItemId
,仅返回0L
或null
不在任何地方使用它。我看不出有任何明显的理由说明UUID会比long
ID的某些值更有价值。断开模式?那是什么?
好吧,看来这个问题可以用更简单,更直接的方式回答... :-)
简而言之,Android允许您将a附加long
到任何ListView
项目,就是这么简单。当系统通知您用户选择时,您会收到三个标识变量,以告诉您选择了什么:
long
您连接到单个元素。由您决定这三种方式中哪一种最适合您的具体情况,但您始终可以选择这三种方式。可以将其long
视为自动附加到商品的标签,只是它更加简单易读。
关于它通常做什么的误解源于一个简单的约定。getItemId()
即使它们实际上没有使用此第三标识,所有适配器也必须提供一个。因此,按照惯例,这些适配器(包括SDK中的许多示例或整个Web)仅position
出于单一原因返回:它始终是唯一的。但是,如果适配器返回position
,这实际上意味着它根本不希望使用此功能,因为position
已经知道了。
因此,如果您需要返回您认为合适的任何其他值,请随时这样做:
@Override
public long getItemId(int position) {
return data.get(position).Id;
}
getItemId()
...如果/如果您的自定义适配器中未重写此方法,将会发生什么?
该getItemId
方法主要用于与SQLite数据库支持的游标一起使用。它将返回位置1的项目的基础光标的id字段。
在您的情况下,位置1上没有该项目的ID:我假设ArrayAdapter的实现只返回-1或0。
编辑:实际上,它只是返回位置:在这种情况下1
。
-1
。这是实现方式assert false : "TODO"; return -1;
我想提一提,在实现之后getItem
,getItemId
您可以使用ListView.getItemAtPosition和ListView.getItemIdAtPosition直接访问您的数据,而不用通过适配器。在实现onClick侦听器时,这可能特别有用。
如果实施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();
}
现在,您的项目ID取决于coverUrl和title字段的值,如果您随后进行更改并调用notifyDataSetChanged()
适配器,则适配器将调用每个元素的getItemId()方法并仅更新ID已更改的thouse项目。
如果您正在执行一些“繁重”的操作,这将非常有用getView()
。
顺便说一句:如果您希望此方法有效,则需要确保您的hasStableIds()
方法返回false;
hasStableIds()
返回假?在我看来,从同一字符串计算出的哈希码每次都会返回相同的值,根据docs,这是一个稳定的ID 。
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);
}
});
getItemId()
在ArrayAdapter()
始终返回-1
与assert false : "TODO"; return -1;