AndroidクラスBaseAdapterのメソッドgetItemおよびgetItemIdの目的は何ですか?


155

私は、メソッドの目的についての興味getItemgetItemIdAndroidのSDKのクラスアダプタインチ

説明から、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れたものは、データベース内のオブジェクトへの参照である可能性があり、そのオブジェクトに対してさまざまな操作(更新/削除など)を実行できます。

したがって、myListData.get(position).getId()使用できるように生データオブジェクトからIDにアクセスする代わりにadapter.getItemId(position)

これらのメソッドを使用する必要があると感じた例の1つは、SeparatedListViewAdapterを使用するプロジェクトです。このアダプターには複数の異なる種類のアダプターを含めることができ、それぞれが異なるタイプ(通常)のデータを表します。呼び出すときgetItem(position)SeparatedListViewAdapter、返されるオブジェクトは、位置は、あなたがそれを送ることである「セクション」に応じて異なる場合があります。

たとえば、リストに2つのセクション(フルーツとキャンディー)がある場合:フルーツセクションのアイテムを使用getItem(position)していpositionた場合、キャンディーのアイテムをポイントしてリクエストした場合とは異なるオブジェクトを受け取ります。セクション。次に、どのような種類のデータが返されているかを表す、ある種の定数ID値を返すか、または使用して、どのオブジェクトを持っているかを判別します。getItem(position)positiongetItemId(position)getItem(position)instanceof

私が述べたこと以外に、私はこれらの方法を使用する必要が本当にあると感じたことはありません


7
SQLに関連しないアダプターの場合、getItemIdにはまだ目的がありますか?もしそうなら、何を返すべきですか?ポジション?
Android開発者

1
メソッドの目的や使用法は主に開発者次第であり、データベース駆動型アプリとは関係ありません。明確に、読みやすく、再利用可能なコードを作成するために、それを利用してください。
ジェームズ

1
そうかもね。 getViewgetCountgetViewTypeCount、などを具体的に正しくリストビューのUIを示すために使用されています。その他の機能だけでヘルプが、私は頻繁に使用するが、そのようなアイテムをクリックすると、さらにアクションを実行するなど、他の機能などを実装作成getItemの内側getView
ジェームズ・

1
@NicolasZozol確かに-実装せずにgetItemId返す0Lnull、どこでも使用しないのが安全です。UUIDがlongIDの単なる値よりも価値がある理由は明らかではありません。切断モード?あれは何でしょう?
ジェームズ2014年

1
@binnyb:Nicolasは、UUIDがあれば、ネットワークに接続していなくても、有効な一意のIDを(たとえば、モバイルデバイス上で)作成することが依然として可能であることを意味しました。
2014

32

さて、この質問はより簡単で簡単な方法で答えられるようです... :-)

簡単に言うと、Androidではlong任意のListViewアイテムにをアタッチできます。これはとても簡単です。システムがユーザーの選択を通知すると、何が選択されたかを示す3つの識別変数​​を受け取ります。

  • ビュー自体への参照、
  • リスト内での数値の位置
  • これlongを個々の要素にアタッチしました。

特定のケースでこれらの3つのうちどれが最も扱いやすいかを決めるのはあなた次第ですが、常に3つすべてを選択する必要があります。これlongは、アイテムに自動的に添付されるタグと考えてください。それだけでなく、読みやすくなっています。

それが通常何をするかについての誤解は、単純な慣習から生じます。すべてのアダプターは、getItemId()実際にはこの3番目のIDを使用しない場合でも、提供する必要があります。したがって、慣例により、これらのアダプター(SDKのサンプルやWeb全体のサンプルを含む)positionは、1つの理由で単純に戻ります。それは常に一意であるためです。それでも、アダプターがを返した場合position、これは本当に既知の機能なので、この機能をまったく使用しないことを意味positionます。

したがって、適切と思われる他の値を返す必要がある場合は、遠慮なくそうしてください。

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

1
これについての素晴らしい説明getItemId()...カスタムアダプターでこのメソッドがオーバーライドされない場合/場合はどうなりますか?
dentex 14

基本クラスで抽象としてマークされている必要があります。もちろん、元のアダプターをオーバーライドするものをオーバーライドしない限り。省略してみてください。Eclipseが文句を言う場合は、そうする必要があります。:-)
ガボール

ありがとう。私は常にこのメソッドを警告なしでコメントアウトしてきました。私が持っているCustomAdapterはArrayAdapter <CustomListItem>を拡張し、 "ホルダーパターン"を使用して、同様にgetCount()、のgetItem(...)とgetViewメソッド(...)で。ちょうど好奇心から…
dentex 14

そうです、ArrayAdapterBaseAdapterを拡張し、すでに独自の実装を提供しているので、それを行うことができます。
ガーボル

そして、単純な配列であれば、それで十分です。ただし、たとえばデータベースのアイテムを表示する場合など、別のケースを考えてみてください。次に、おそらくBaseAdapterを拡張し、この長いIDを使用してデータベースキーを格納できます。ユーザーが何かを選択すると、選択したレコードのキーがid引数を介して直接返されます。たとえば、データベースからすぐにロードできます。Androidがより広いものではなく長いものを決定したため、数字キーを使用する必要があるという唯一の問題。
ガーボル

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

実装後getItemListView.getItemAtPositionListView.getItemIdAtPositiongetItemId使用して、アダプターを経由する代わりに、直接データにアクセスできることを述べておきます。これは、onClickリスナーを実装するときに特に役立ちます。


3
これは、リストビューにヘッダーがあり、クリックハンドラーに渡される位置が1つずれている場合に非常に便利です
エントロピー

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

ところで:これを機能させるには、hasStableIds()メソッドがfalseを返すことを確認する必要があります。


これは貴重な観察ですが、この選択的な更新メカニズムを裏付けるデータを提供できますか?
Jaime Agudo 2017

なぜhasStableIds()false を返す必要があるのですか?同じ文字列から計算されたハッシュコードは毎回同じ値を返すように思えます。これはドキュメントによれば安定したID です。
Big McLargeHuge

hashCodeを使用すると、2つの文字
列に

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.