Android 클래스 BaseAdapter에서 getItem 및 getItemId 메소드의 의도는 무엇입니까?


155

안드로이드 SDK 의 메소드 getItemgetItemId클래스 어댑터 의 목적이 궁금합니다 .

설명 getItem에서 기본 데이터를 반환해야합니다. 따라서 이름 배열이 ["cat","dog","red"]있고이를 사용하여 어댑터 a를 만들면 a.getItem(1)"dog"을 반환해야합니다. 맞습니까? 무엇을 a.getItemId(1)반환 해야 합니까?

실제로 이러한 방법을 사용했다면 예를 들어 주시겠습니까?


16
+1 훌륭한 질문입니다. 내가 지적하고 싶은 getItemId()ArrayAdapter()항상 반환 -1assert false : "TODO"; return -1;
RDS

답변:


86

이 방법을 목록 데이터에 액세스하는 더 깔끔한 방법으로보고 있습니다. 같은 것을 통해 내 어댑터 객체에 직접 액세스하는 대신 myListData.get(position)간단히 어댑터를 호출 할 수 있습니다 adapter.get(position).

동일합니다 getItemId. 일반적으로 목록에서 객체의 고유 ID를 기반으로 일부 작업을 실행하려고 할 때이 방법을 사용합니다. 데이터베이스 작업시 특히 유용합니다. 반환 id된 것은 데이터베이스의 객체에 대한 참조 일 수 있으며 (업데이트 / 삭제 / 등) 다른 작업을 수행 할 수 있습니다.

따라서 원시 데이터 객체에서 ID에 액세스하는 대신을 myListData.get(position).getId()사용할 수 있습니다 adapter.getItemId(position).

이 메소드를 사용해야한다고 생각한 곳의 예는 SeparatedListViewAdapter를 사용하는 프로젝트였습니다 . 이 어댑터에는 여러 유형의 어댑터가 포함될 수 있으며, 각기 다른 유형의 데이터를 나타냅니다 (일반적으로). 호출 할 때 getItem(position)SeparatedListViewAdapter, 반환 된 객체는 위치가 당신이 그것을 보내이다 "섹션"에 따라 다를 수 있습니다.

예를 들어, 당신은 당신의 목록 (과일 사탕)에 2 개 섹션을 가지고 : 당신이 사용하는 경우 getItem(position)position의 항목에 우연히 과일 요청한 것보다, 다른 객체를받을 섹션 getItem(position)으로 position의 항목을 가리키는 사탕 부분. 그런 다음 getItemId(position)어떤 종류의 데이터 getItem(position)가 반환 되는지 나타내는 상수 ID 값을 반환하거나 사용중인 instanceof개체를 결정하는 데 사용할 수 있습니다.

내가 언급 한 것 외에는,이 방법들을 사용해야한다고 생각한 적이 없다


7
비 SQL 관련 어댑터의 경우 getItemId에 여전히 목적이 있습니까? 그렇다면 무엇을 반환해야합니까? 위치?
안드로이드 개발자

1
이 방법의 목적 또는 사용은 주로 개발자에게 달려 있으며 데이터베이스 기반 앱과 관련이 없습니다. 명확하고 읽기 쉽고 재사용 가능한 코드를 작성하기 위해이를 활용하십시오.
제임스

1
그래 getView, getCount, getViewTypeCount, 등 제대로 목록보기 UI를 보여주는 용으로 사용된다. 다른 함수는 단순히 getItem내부에서 자주 사용하지만 항목을 클릭 할 때 추가 작업을 수행하는 것과 같은 다른 기능을 구현하는 데 도움이 됩니다.getView
james

1
@NicolasZozol Sure- 구현하지 않는 것이 안전합니다. getItemId반품 0L하거나 null어디서나 사용하지 마십시오. UUID가 longID의 가치보다 더 가치있는 이유는 없습니다 . 연결 해제 모드? 그게 뭐야?
james

1
@binnyb : Nicolas는 UUID를 사용하면 네트워크 연결 없이도 유효한 고유 ID (예 : 모바일 장치)를 만들 수 있음을 의미했습니다.
Levite

32

글쎄,이 질문은 더 간단하고 간단하게 대답 할 수있는 것 같습니다 ... :-)

간단히 말해서, Android를 사용하면 long모든 ListView항목 에 a 를 첨부 할 수 있습니다 . 간단합니다. 시스템이 사용자 선택을 통지하면, 선택된 것을 알려주는 세 가지 식별 변수가 수신됩니다 .

  • 뷰 자체에 대한 참조
  • 목록에서 숫자 위치
  • 이것은 long당신 이 개별 요소에 첨부했습니다.

이 세 가지 중 어떤 것이 가장 특정한 경우에 가장 다루기 쉬운 지 결정하는 것은 전적으로 귀하의 몫입니다. 그러나 세 가지 모두 항상 선택할 수 있습니다. 이것을 long항목에 자동으로 첨부 된 태그로 생각하면 더 간단하고 읽기 쉽습니다.

일반적으로하는 일에 대한 오해는 간단한 관습에서 비롯됩니다. 모든 어댑터는 getItemId()실제로이 세 번째 식별을 사용하지 않더라도 짝수 를 제공해야합니다 . 따라서 일반적으로 이러한 어댑터 (SDK의 샘플 또는 웹의 모든 샘플을 포함) position는 단일 이유 때문에 단순히 반환 됩니다. 항상 고유합니다. 그러나 어댑터를 반환하는 경우 position,이 정말 의미 가 전혀이 기능을 사용하지 않기 때문에 position이미 알려져있다 어쨌든.

따라서 적합하다고 생각되는 다른 값을 반환 해야하는 경우 자유롭게 그렇게하십시오.

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

1
이것에 대한 좋은 설명 getItemId()...이 방법이 사용자 정의 어댑터에서 무시되지 않으면 어떻게됩니까?
dentex

기본 수업에서 초록으로 표시되어야합니다. 물론 원래 어댑터를 대체하는 것을 대체하지 않는 한. 그것을 떠나려고 노력하고, 이클립스가 불평하면 당신은해야합니다. :-)
Gábor

감사. 나는 항상이 방법을 경고없이 주석 처리했습니다. "홀더 패턴"을 사용하여 getA (), getItem (...) 및 getView (...)를 사용하여 ArrayAdapter <CustomListItem>확장 하는 CustomAdapter 가 있습니다 . 그냥 호기심에서 ...
dentex

ArrayAdapterBaseAdapter를 확장 하고 이미 자체 구현을 제공 하기 때문에 그렇게 할 수 있습니다 .
Gábor

그리고 간단한 배열로 괜찮습니다. 그러나 데이터베이스의 항목을 표시하려는 경우 다른 경우를 고려하십시오. 그런 다음 BaseAdapter를 확장 하고이 긴 ID를 사용하여 데이터베이스 키를 저장할 수 있습니다. 사용자가 무언가를 선택하면 id 인수 를 통해 선택한 레코드의 키를 직접 가져옵니다 . 그런 다음 예를 들어 데이터베이스에서 즉시로드 할 수 있습니다. 안드로이드가 더 넓은 것이 아니라 긴 것을 결정했기 때문에 숫자 키를 사용해야하는 문제 만.
Gábor

6

getItemId방법은 주로 SQLite 데이터베이스가 지원하는 커서와 함께 작동하도록 설계되었습니다. 위치 1에있는 항목에 대한 기본 커서의 id 필드를 반환합니다.

귀하의 경우 1 위치의 항목에 대한 ID가 없습니다. ArrayAdapter의 구현이 -1 또는 0을 반환한다고 가정합니다.

편집 : 실제로, 그것은 단지 위치를 반환합니다 :이 경우 1.


2
아니요를 반환합니다 -1. 구현은 다음과 같습니다assert false : "TODO"; return -1;
rds

5
안드로이드 4.1.1에서, 위치를 반환합니다 : grepcode.com/file/repository.grepcode.com/java/ext/…
emmby

4

내가 구현 한 후 그 언급하고자 getItem하고 getItemId당신이 사용할 수있는 ListView.getItemAtPositionListView.getItemIdAtPosition을 대신 어댑터를 통해가는, 당신에게 데이터에 직접 액세스 할 수 있습니다. 이것은 onClick 리스너를 구현할 때 특히 유용 할 수 있습니다.


3
당신이 당신의 목록보기에 헤더를 가지고 위치가 하나 꺼져 핸들러 클릭에 전달 된 경우는 실제로 매우 유용합니다
엔트로피

4

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

BTW :이 기능을 사용하려면 hasStableIds()메소드가 false를 리턴 하는지 확인해야합니다 .


이것은 귀중한 관찰입니다.이 선택적 업데이트 메커니즘을 뒷받침 할 데이터를 제공 할 수 있습니까?
Jaime Agudo

hasStableIds()거짓 을 반환 해야 합니까? 동일한 문자열에서 계산 된 해시 코드는 매번 동일한 값을 반환하는 것으로 보입니다. 이것은 docs 에 따라 안정적인 ID 입니다.
Big McLargeHuge

해시 코드를 사용하여 두 개의 문자열에 true를 돌려 수 있음을 고려
htafoya

2

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);
    }
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.