एंड्रॉइड क्लास बेस एडेप्टर में getItem और getItemId के तरीकों का इरादा क्या है?


155

मैं एंड्रॉइड एसडीके में विधियों के उद्देश्य getItemऔर getItemIdक्लास एडॉप्टर के बारे में उत्सुक हूं ।

विवरण से, ऐसा लगता है कि getItemअंतर्निहित डेटा को वापस करना चाहिए। इसलिए, अगर मेरे पास नामों की एक सरणी है ["cat","dog","red"]और मैं aउस का उपयोग करके एक एडाप्टर बनाता हूं , तो a.getItem(1)"कुत्ते" को वापस करना चाहिए, सही? क्या a.getItemId(1)लौटना चाहिए ?

यदि आपने अभ्यास में इन विधियों का उपयोग किया है, तो क्या आप एक उदाहरण प्रदान कर सकते हैं?


16
+1 उत्कृष्ट प्रश्न। मैं बाहर बात करने के लिए चाहता हूँ कि getItemId()में ArrayAdapter()हमेशा रिटर्न -1के साथassert false : "TODO"; return -1;
आरडीएस

जवाबों:


86

मैं अपनी सूची के डेटा तक पहुंचने के लिए इन तरीकों को एक क्लीनर दृष्टिकोण के रूप में देखता हूं। मेरे एडॉप्टर ऑब्जेक्ट को सीधे कुछ के माध्यम से एक्सेस करने के बजाय जैसे myListData.get(position)मैं बस एडेप्टर को कॉल कर सकता हूं adapter.get(position)

उसी के लिए जाता है getItemId। आमतौर पर मैं इस पद्धति का उपयोग तब करता हूं जब मैं सूची में किसी ऑब्जेक्ट की अद्वितीय आईडी के आधार पर कुछ कार्य निष्पादित करना चाहता हूं। डेटाबेस के साथ काम करते समय यह विशेष रूप से उपयोगी है। लौटा idडेटाबेस में किसी ऑब्जेक्ट का संदर्भ हो सकता है जो मैं तब (अपडेट / हटाएं / आदि) पर अलग-अलग ऑपरेशन कर सकता था।

तो जैसे myListData.get(position).getId()आप उपयोग कर सकते हैं कच्चे डेटा ऑब्जेक्ट से आईडी तक पहुँचने के बजाय adapter.getItemId(position)

एक उदाहरण जहां मैंने महसूस किया है कि मुझे इन विधियों का उपयोग करने की आवश्यकता है, प्रोजेक्ट में अलग-अलगListViewAdapter का उपयोग कर रहा था । इस एडेप्टर में कई अलग-अलग प्रकार के एडेप्टर हो सकते हैं, प्रत्येक एक अलग प्रकार (आमतौर पर) के डेटा का प्रतिनिधित्व करते हैं। जब कॉल getItem(position)किया जाता है SeparatedListViewAdapter, तो दी गई वस्तु भिन्न हो सकती है, जिसके आधार पर "खंड" स्थिति यह है कि आप इसे भेजते हैं।

उदाहरण के लिए, यदि आपकी सूची में 2 खंड थे (फल और कैंडी): यदि आप उपयोग किया getItem(position)और फल खंड positionमें एक आइटम पर हुआ , तो आपको कैंडी में एक आइटम की ओर इशारा करने के साथ अनुरोध करने की तुलना में एक अलग वस्तु प्राप्त होगी। अनुभाग। फिर आप किसी प्रकार के निरंतर आईडी मान को वापस कर सकते हैं जिसमें यह दर्शाया जाता है कि किस प्रकार का डेटा वापस आ रहा है, या यह निर्धारित करने के लिए कि आपके पास कौन सी वस्तु है।getItem(position)positiongetItemId(position)getItem(position)instanceof

मैंने जो उल्लेख किया है, उसके अलावा, मुझे ऐसा कभी नहीं लगा कि मुझे वास्तव में इन तरीकों का उपयोग करने की आवश्यकता है


7
गैर-sql संबंधित एडेप्टर के लिए, getItemId अभी भी एक उद्देश्य है? यदि हां, तो क्या लौटाया जाना चाहिए? स्थान?
Android डेवलपर

1
विधि का उद्देश्य या उपयोग मुख्य रूप से डेवलपर के लिए है और डेटाबेस संचालित ऐप से जुड़ा नहीं है। स्पष्ट / पठनीय / पुन: प्रयोज्य कोड बनाने के लिए अपने लाभ के लिए इसका उपयोग करें।
जेम्स

1
हाँ, मुझे लगता है कि। getView, getCount, getViewTypeCount, आदि ठीक से अपने सूचीदृश्य यूआई दिखाने के लिए विशेष रूप से किया जाता है। अन्य कार्यों बस मदद इस तरह के एक आइटम, आदि पर क्लिक हालांकि मैं अक्सर उपयोग पर आगे कार्रवाई प्रदर्शन के रूप में अन्य कार्यक्षमताओं को लागू बनाने के getItemअंदरgetView
जेम्स

1
@ नाइसोलज़ोज़ोल ज़रूर- इसे लागू करना सुरक्षित नहीं है getItemId, बस वापस लौटें 0Lया nullकहीं भी इसका इस्तेमाल न करें। मुझे कोई स्पष्ट कारण नहीं दिख रहा है कि एक यूयूआईडी longआईडी के लिए सिर्फ कुछ मूल्य से अधिक मूल्यवान क्यों होगा । डिस्कनेक्टेड मोड? वह क्या है?
james

1
@binnyb: निकोलस का मतलब था कि यूयूआईडी के साथ, बिना नेटवर्क कनेक्शन के भी, वैध यूनिक आईडी (जैसे आपके मोबाइल डिवाइस पर) बनाना संभव है।
लेविती

32

खैर, ऐसा लगता है कि इस सवाल का जवाब सरल और अधिक सरल तरीके से दिया जा सकता है ... :-)

सीधे शब्दों में कहें, एंड्रॉइड आपको longकिसी भी ListViewआइटम को संलग्न करने की अनुमति देता है , यह इतना आसान है। जब सिस्टम आपको उपयोगकर्ता चयन के बारे में सूचित करता है, तो आपको यह बताने के लिए तीन पहचान चर मिलते हैं कि क्या चुना गया था:

  • खुद को देखने के लिए एक संदर्भ,
  • सूची में इसकी संख्यात्मक स्थिति,
  • यह longआप व्यक्तिगत तत्वों से जुड़ा हुआ है।

यह आपको तय करना है कि इन तीनों में से कौन सा आपके लिए अपने विशेष मामले में संभालना सबसे आसान है, लेकिन आपके पास हर समय चुनने के लिए तीनों हैं। इसे longएक टैग के रूप में आइटम से स्वचालित रूप से जुड़ा हुआ समझें, केवल यह कि यह और भी सरल और आसानी से पढ़ने के लिए आसान है।

आम तौर पर एक साधारण सम्मेलन से उपजी इस बारे में गलतफहमी। सभी एडेप्टर को एक प्रदान करना होगा, getItemId()भले ही वे वास्तव में इस तीसरी पहचान का उपयोग न करें। इसलिए, कन्वेंशन द्वारा, उन एडेप्टर (एसडीके या वेब के चारों ओर नमूनों में कई सहित) बस positionएक ही कारण से लौटते हैं : यह हमेशा अद्वितीय होता है। फिर भी, यदि कोई एडाप्टर लौटाता है, तो positionइसका वास्तव में मतलब है कि वह इस सुविधा का उपयोग नहीं करना चाहता है, क्योंकि positionपहले से ही ज्ञात है, वैसे भी।

इसलिए, यदि आपको किसी अन्य मूल्य को वापस करने की आवश्यकता है जिसे आप फिट देखते हैं, तो ऐसा करने के लिए स्वतंत्र महसूस करें:

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

1
इसके लिए अच्छा स्पष्टीकरण getItemId()... जब आपके कस्टम एडॉप्टर में इस विधि को ओवरराइड नहीं किया जाता है तो क्या होगा?
डेंटेक्स

बेस क्लास में अमूर्त होने के नाते, आपको करना होगा। जब तक आप मूल एडॉप्टर को ओवरराइड करने वाली किसी चीज को ओवरराइड नहीं करते, तब तक। इसे बाहर छोड़ने की कोशिश करें, और यदि ग्रहण शिकायत करता है तो आपको करना होगा। :-)
गैबोर

धन्यवाद। मैंने हमेशा इस पद्धति को बिना किसी चेतावनी के टिप्पणी की है। मेरे पास "धारक पैटर्न" का उपयोग करते हुए getCount (), getItem (...) और getView (...) के साथ एक ArrayAdapter <CustomListItem> का विस्तार है । बस जिज्ञासा से बाहर ...
डेंटेक्स

हाँ, आपको लगता है कि क्योंकि कर सकते हैं ArrayAdapter फैली BaseAdapter और पहले से ही अपने स्वयं के कार्यान्वयन प्रदान करता है।
गैबोर

और एक साधारण सरणी के साथ, यह सब ठीक है। उदाहरण के लिए, जब आप डेटाबेस से आइटम प्रदर्शित करना चाहते हैं, तो बस एक और मामले पर विचार करें। फिर आप संभवतः बेस एडेप्टर का विस्तार करेंगे और डेटाबेस कुंजी को स्टोर करने के लिए इस लंबी आईडी का उपयोग कर सकते हैं। जब उपयोगकर्ता कुछ का चयन करता है, तो आपको सीधे आईडी तर्क के माध्यम से चयनित रिकॉर्ड की कुंजी वापस मिल जाएगी । आप इसे डेटाबेस से तुरंत लोड कर सकते हैं, उदाहरण के लिए। केवल समस्या है कि आपको संख्यात्मक कुंजियों का उपयोग करना है क्योंकि एंड्रॉइड ने कुछ व्यापक के बजाय एक लंबे समय पर निर्णय लिया।
गैबोर

6

यह getItemIdविधि काफी हद तक Cursors के साथ काम करने के लिए डिज़ाइन की गई है जो SQLite डेटाबेस द्वारा समर्थित हैं। यह स्थिति 1 में आइटम के लिए अंतर्निहित कर्सर आईडी फ़ील्ड को वापस कर देगा।

आपके मामले में स्थिति 1 में आइटम के लिए कोई आईडी नहीं है: मैं मान रहा हूं कि ArrayAdapter का कार्यान्वयन केवल -1 या 0 देता है।

संपादित करें: वास्तव में, यह सिर्फ स्थिति लौटाता है: इस मामले में 1


2
नहीं यह लौटता है -1। यहाँ कार्यान्वयन हैassert false : "TODO"; return -1;
आरडी

5
Android 4.1.1 के अनुसार, यह स्थिति लौटाता है: grepcode.com/file/repository.grepcode.com/java/ext/…
emmby

4

मैं यह उल्लेख करना चाहूंगा कि लागू करने के बाद getItemऔर getItemIdआप एडॉप्टर के माध्यम से जाने के बजाय सीधे डेटा तक पहुंचने के लिए ListView.getItemAtPosition और ListView.getItgetIemAtPosition का उपयोग कर सकते हैं । यह ऑनक्लिक श्रोता को लागू करते समय विशेष रूप से उपयोगी हो सकता है।


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

अब आपकी आइटम आईडी कवर यूआरएल और शीर्षक फ़ील्ड के मानों पर निर्भर करती है और यदि आप तब बदलते हैं और notifyDataSetChanged()अपने एडेप्टर पर कॉल करते हैं, तो एडेप्टर प्रत्येक तत्व के getItemId () विधि को कॉल करेगा और केवल thouse आइटम को अपडेट करेगा जो आईडी बदल गई है।

यह बहुत उपयोगी है अगर आप में कुछ "भारी" ऑपरेशन कर रहे हैं getView()

BTW: यदि आप यह काम करना चाहते हैं, तो आपको यह सुनिश्चित करने की आवश्यकता है कि आपका hasStableIds()तरीका गलत है;


यह एक मूल्यवान अवलोकन है, क्या आप इस चयनात्मक अद्यतन तंत्र को वापस करने के लिए कुछ डेटा प्रदान कर सकते हैं?
Jaime Agudo

hasStableIds()असत्य क्यों लौटाना चाहिए ? यह मुझे लगता है कि एक ही स्ट्रिंग से गणना की गई हैशकोड हर बार समान मान लौटाएगा, जो डॉक्स के अनुसार एक स्थिर आईडी है ।
बिग मैकलेरजैग

विचार करें कि
हैशकोड

2

getItemया getItemIdमुख्य रूप से सूची में आइटम के साथ संलग्न डेटा के लिए डिज़ाइन की गई कुछ विधि हैं। के मामले में 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);
    }
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.