2011-07-15 60 views
138

我對Android SDK中的Adapter類中的方法getItemgetItemId的用途感到好奇。Android類BaseAdapter中getItem和getItemId方法的意圖是什麼?

從描述,似乎getItem應該返回的基礎數據。所以,如果我有一個名稱爲["cat","dog","red"]的數組,我創建一個適配器a使用那個,那麼a.getItem(1)應該返回「狗」,正確嗎? a.getItemId(1)應該返回什麼?

如果你用到了實踐這些方法,你能提供一個例子嗎?

+14

+1優秀的問題。我想指出ArrayAdapter()中的'getItemId()'總是返回'-1',其中'assert false:「TODO」; \t \t return -1;' – rds

回答

74

我將這些方法看作是訪問我的列表數據的更簡潔的方法。而不是直接通過像myListData.get(position)這樣的東西來訪問我的適配器對象,我可以簡單地調用適配器,如adapter.get(position)

這同樣適用於getItemId。通常,當我想根據列表中對象的唯一標識執行某個任務時,我會使用此方法。這在使用數據庫時特別有用。返回的id可能是對數據庫中對象的引用,然後我可以對(update/delete/etc)執行不同的操作。

因此,您可以使用adapter.getItemId(position)來代替從原始數據對象(如myListData.get(position).getId())訪問ID。在那裏我已經覺得我需要使用這些方法

一個例子是在使用SeparatedListViewAdapter的項目。此適配器可以包含多種不同類型的適配器,每個適配器都代表不同類型的數據(通常)。當在SeparatedListViewAdapter上調用getItem(position)時,返回的對象可能會有所不同,具體取決於您發送位置的「部分」位置。

例如,如果你在你的列表(水果和糖果)有2個部分:如果您使用getItem(position)position碰巧在在水果區塊中的項目,您會收到一個不同的對象比,如果你要求getItem(position)position指向糖果部分中的項目。然後,您可能會在getItemId(position)中返回某種常數ID值,該值代表什麼樣的數據getItem(position)正在返回,或者使用instanceof來確定您擁有哪個對象。

除了我所提到的東西,我從來沒有覺得我真的需要使用這些方法

+7

對於非sql相關的適配器,getItemId仍然有目的嗎?如果是的話,應該返回什麼?位置? –

+1

該方法的目的或用途主要取決於開發人員,而不是綁定到數據庫驅動的應用程序。利用它來創造清晰/可讀/可重用的代碼。 – binnyb

+0

我明白了。所以這就是爲什麼說明太模糊了?它沒有以任何方式被API使用,就像getItem一樣,對吧? API使用的唯一東西是getView和getCount? –

5

getItemId方法主要設計了由SQLite數據庫支持遊標工作。它會返回位置1中項目的底層光標的ID字段。

在您的情況下,位置1中的項目沒有ID:我假設ArrayAdapter的實現僅返回-1或0.

編輯:實際上,它只是返回位置:在這種情況下1

+2

不,它返回'-1'。這是執行'assert false:「TODO」; 返回-1;' – rds

+4

從Android 4.1.1開始,它返回位置:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/ android/widget/ArrayAdapter.java#ArrayAdapter.getItemId%28int%29 – emmby

28

嗯,看來這個問題可以在一個更簡單,更直接的方式來回答......:-)

簡而言之,Android允許您附加long到任何ListView項目,就這麼簡單。當系統通知您的用戶選擇,您會收到識別變量來告訴你什麼選擇:

  • 視圖本身的引用,
  • 其在列表中的數值位置,
  • 這個long你附加到個別元素。

這是由您來決定這三個是哪一個最容易處理您的具體情況,但你有三個可以選擇的所有時間。將這個long想象成自動附加到該項目的標籤,只是它更簡單易讀。

什麼它通常不會從一個簡單的約定莖的誤解。所有適配器必須提供getItemId(),即使它們實際上未使用此第三個標識。因此,按照慣例,這些適配器(包括許多在SDK或所有網絡上的樣品)只是爲一個單一的原因返回position:它總是獨一無二的。不過,如果一個適配器返回position,這實際上意味着它不希望使用此功能在所有,因爲position已經知道,反正。

所以,如果你需要返回你認爲合適的任何其他數值,隨時可以這樣做:

@Override 
public long getItemId(int position) { 
    return data.get(position).Id; 
} 
+1

這個'getItemId()'的很好的解釋...當/如果這個方法在你的自定義適配器中沒有被覆蓋時會發生什麼? – dentex

+0

在基類中被標記爲抽象,你必須。除非你重寫覆蓋原始適配器的東西,當然。儘量不要說,如果Eclipse抱怨,那麼你必須。 :-) –

+0

謝謝。我一直有這種方法註釋掉沒有警告。我有一個** CustomAdapter擴展ArrayAdapter **與getCount(),getItem(...)和getView(...),使用「持有人模式」。只是出於好奇... – dentex

3

我想提一提,實施getItemgetItemId後,您可以使用ListView.getItemAtPositionListView.getItemIdAtPosition直接訪問您的數據,而不是通過適配器。這在實現onClick偵聽器時可能特別有用。

+2

如果你在你的listview上有一個標題,並且傳遞給點擊處理程序的位置關閉了一個,這確實非常有用 – entropy

3

如果實施正確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標題字段,如果你改變然後打電話notifyDataSetChanged()您的適配器,則適配器將調用每個元素的getItemId()方法和更新僅ID已更改thouse項目。

如果在getView()中執行一些「重」操作,這非常有用。

順便說一句:如果你想要這個工作,你需要確保你的hasStableIds()方法返回false;

+0

這是一個很有價值的觀察,你能否提供一些數據來支持這個選擇性更新機制? –

1

getItemgetItemId是主要設計用於附加列表中的項目數據的方法。在getItem的情況下,您可以傳遞將附加到列表中的項目的任何對象。通常人們會返回nullgetItemId是您可以使用列表中的同一項目附加的任何唯一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); 
    } 
}); 
相關問題