कस्टम लिस्टव्यू एडॉप्टर getView मेथड को कई बार, और बिना किसी सुसंगत क्रम के कहा जाता है


162

मेरे पास एक कस्टम सूची एडाप्टर है:

class ResultsListAdapter extends ArrayAdapter<RecordItem> {

ओवरराइड 'getView' पद्धति में मैं यह जांचने के लिए एक प्रिंट करता हूं कि स्थिति क्या है और यह कन्वर्ट व्यू है या नहीं:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        System.out.println("getView " + position + " " + convertView);

इसका आउटपुट (जब सूची पहली बार प्रदर्शित होती है, तब तक कोई उपयोगकर्ता इनपुट नहीं)

04-11 16:24:05.860: INFO/System.out(681): getView 0 null  
04-11 16:24:29.020: INFO/System.out(681): getView 1 android.widget.RelativeLayout@43d415d8  
04-11 16:25:48.070: INFO/System.out(681): getView 2 android.widget.RelativeLayout@43d415d8  
04-11 16:25:49.110: INFO/System.out(681): getView 3 android.widget.RelativeLayout@43d415d8  
04-11 16:25:49.710: INFO/System.out(681): getView 0 android.widget.RelativeLayout@43d415d8  
04-11 16:25:50.251: INFO/System.out(681): getView 1 null  
04-11 16:26:01.300: INFO/System.out(681): getView 2 null  
04-11 16:26:02.020: INFO/System.out(681): getView 3 null  
04-11 16:28:28.091: INFO/System.out(681): getView 0 null  
04-11 16:37:46.180: INFO/System.out(681): getView 1 android.widget.RelativeLayout@43cff8f0  
04-11 16:37:47.091: INFO/System.out(681): getView 2 android.widget.RelativeLayout@43cff8f0  
04-11 16:37:47.730: INFO/System.out(681): getView 3 android.widget.RelativeLayout@43cff8f0  

AFAIK, हालांकि मुझे यह स्पष्ट रूप से नहीं मिला, getView () को केवल दृश्य पंक्तियों के लिए कहा जाता है। चूंकि मेरा ऐप चार दृश्य पंक्तियों के साथ शुरू होता है, कम से कम स्थिति संख्या 0-3 से साइकिल चलाना समझ में आता है। लेकिन बाकी एक गड़बड़ है:

  • प्रत्येक पंक्ति को तीन बार क्यों कहा जाता है?
  • जब मैंने अभी तक स्क्रॉल नहीं किया है, तो ये कन्वर्ट व्यू कहां से आ रहे हैं?

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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent" 
    android:orientation="vertical" >

    <TextView android:id="@+id/pageDetails"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" />

    <ListView android:id="@+id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" 
        android:drawSelectorOnTop="false" />

</LinearLayout>

और प्रत्येक व्यक्तिगत पंक्ति का लेआउट:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="108dp"    
android:padding="4dp">

<ImageView
    android:id="@+id/thumb"        
    android:layout_width="120dp"
    android:layout_height="fill_parent"        
    android:layout_alignParentTop="true"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_marginRight="8dp"        
    android:src="@drawable/loading" />

<TextView  
    android:id="@+id/price"
    android:layout_width="wrap_content"
    android:layout_height="18dp"         
    android:layout_toRightOf="@id/thumb"
    android:layout_alignParentBottom="true"       
    android:singleLine="true" />

<TextView  
    android:id="@+id/date"
    android:layout_width="wrap_content"
    android:layout_height="18dp"         
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true" 
    android:paddingRight="4dp"       
    android:singleLine="true" />

<TextView
    android:id="@+id/title"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="17dp" 
    android:layout_toRightOf="@id/thumb"
    android:layout_alignParentRight="true"
    android:layout_alignParentTop="true"
    android:paddingRight="4dp"   
    android:layout_alignWithParentIfMissing="true"
    android:gravity="center" />

</RelativeLayout>

अपना समय देने के लिए धन्यवाद

जवाबों:


271

यह कोई मुद्दा नहीं है, इस आदेश की कोई गारंटी नहीं है कि किस क्रम में getView()कॉल किया जाएगा और न ही कितनी बार। अपने विशेष मामले में आप ListViewइसे दे कर सबसे खराब संभव काम कर रहे हैं height=wrap_content। यह ListViewलेआउट समय पर एडॉप्टर से कुछ बच्चों को मापने के लिए मजबूर करता है, यह जानने के लिए कि यह कितना बड़ा होना चाहिए। यह वही है प्रदान करता है ListViewके साथ convertViewsआप के लिए पारित देखें getView()भी इससे पहले कि आप स्क्रॉल करें।


10
मुझे यह एक अच्छा कारण नहीं लगता। यह ठीक है अगर आप बदलना चाहते हैं, लेकिन वर्तमान में इसका जवाब नहीं दे रहे हैं कि यह व्यवहार क्यों कर रहा है?
cdpnet

45
@ LCDpnet उन्होंने कहा कि यह क्यों कर रहा था, आपकी ListViewऊंचाई है wrap_content, इसलिए यह निश्चित नहीं है कि यह ऊँचाई है इसलिए यह कुछ बच्चों को एक प्रकार के परीक्षक के रूप में देखता है कि इसमें क्या फिट होगा। अपने लॉग को जांचने के ListViewलिए इसे बदलें। fill_parentकॉल को नाटकीय रूप से कम किया जाना चाहिए।
ब्लंडेल

4
2.3 और 4.x के युग सूची दृश्य के बीच व्यवहार में काफी बदलाव आया है। दूर ले जाता है, जैसा कि ListView डिज़ाइन किया गया है, आपकी कोशिकाओं / list_items को शुद्ध विचार करने की आवश्यकता है और उन्हें जल्दी से ड्राइंग के लिए अनुकूलित करने की आवश्यकता है। Google I / O के अनुसार सूची दृश्य पर, जहाँ रोमेन ने प्रस्तुत किया, getView को केवल दृश्य प्रतिपादन को अनुकूलित करने और परिणाम को छोड़ने के लिए बुलाया जा सकता है। जबकि मेरी राय में यह iOS UITableView के रूप में डेवलपर के अनुकूल नहीं है, यह है कि यह कैसे है।
कैमरन लोवेल पामर

4
आपको बहुत - बहुत धन्यवाद! मुझे समझ नहीं आया कि getView () को इतनी बार क्यों कहा जाता है। मैंने fill_parent के लिए wra_content को घुमाया और अब मेरा ऐप फिर से तेज हो गया है :)
जूलिया हेक्सेन

28
ListViews को layout_height = wra_content पर सेट करते समय एक चेतावनी होनी चाहिए क्योंकि यह प्रदर्शन की बहुत सारी समस्याओं का कारण बनती है।
nathanielwolf

53

सूची दृश्य match_parentकी layout_heightसंपत्ति पर प्रयास करें । यह getView()इतनी बार बुलाया जा सकेगा।


4
ध्यान दें कि फ्रेड टी लिस्ट व्यू का लेआउट_हाइट निर्दिष्ट करता है ... पंक्ति नहीं, जो कि मैंने कोशिश की है
mblackwell8

8
ध्यान दें कि एपीआई स्तर 8 और उच्चतर के fill_parentसाथ प्रतिस्थापित किया जाना चाहिए match_parent
जेसन एक्सलसन

मुझे लगता है कि getView () विधि कई बार कॉल करेगी, चौड़ाई और ऊंचाई के रूप में सूची दृश्य के लिए match_parent के रूप में सेट करके केवल प्रदर्शन समस्या को हल करें।
Cuong Vo

45

मुझे इस मुद्दे से छुटकारा तब मिला जब मैंने लेआउट_ एक्सपोज़र और लेआउट_हाइट दोनों को मैच_परेंट में बदल दिया (केवल लेआउट_हाइट बदलने में मदद मिली)।


यदि आपके पास नेस्टेड आइटम हैं, तो उपयोगी नोट देखें। आपको मिलान के लिए "उच्चतम" एक को बदलना होगा । आशा है कि यह किसी की मदद करता है।


एक शब्द दोस्त "भयानक" लेकिन पता नहीं क्यों wra_content समस्या पैदा कर रहा है। इससे मेरी समस्या हल हो गई।
एंड्रॉयड किलर

@AndroidKiller जब आप का उपयोग करें wrap_content, तो ListViewपता नहीं है आइटम कितना सूची रहे हैं सूची की सामग्री वहाँ बनने के लिए, thats क्यों ListViewकी कोशिश करता कई पंक्तियों के रूप में बनाने के लिए के रूप में यह सोचता है कि प्रदर्शन करने के लिए उपयुक्त हैं, और जब आप का उपयोग करें fill_parentया match_parent, ListViewसोचता है, ठीक है, मेरे ऊंचाई है xऔर मैं की जरूरत है nपंक्तियों की संख्या को दिखाने के लिए।
आदिल सूमो

आपको बहुत - बहुत धन्यवाद ! इस व्यवहार के साथ कई कॉल की वजह से छवियां बेतरतीब ढंग से बदल रही थीं ... अब यह शुरुआत से ठीक है।
चोस्ताकोविच

7

मैं आपके "क्यों" प्रश्न का उत्तर देने में सक्षम नहीं हूं, लेकिन मेरे पास चिड़चिड़ाहट की समस्या का एक समाधान है " दोहराए जाने वाले आइटमों को दोहराते हुए " समस्या (यदि आपके पास उर संग्रह में आइटम हैं जो स्क्रीन की ऊंचाई से अधिक हैं)।

जैसा कि ऊपर कई लोगों का उल्लेख किया है, रखने layout_height: एंड्रॉयड की संपत्ति ListVew के रूप में टैग fill_parent

और getView () फ़ंक्शन के बारे में, समाधान एक स्थिर वर्ग का उपयोग करना है जिसे ViewHolder कहा जाता है । की जाँच करें इस उदाहरण। यह उर एरे या एरेक्लोलेशन में सभी वस्तुओं को जोड़ने का काम सफलतापूर्वक करता है।

उम्मीद है कि यह दोस्तों की मदद करता है !!

बेस्ट सादर, सिद्धांत


Android के शुरुआती संस्करण (पूर्व ICS) में ViewHolder पैटर्न का उपयोग करने के बारे में सतर्क रहें क्योंकि यह आपको MemoryLeak अपवाद की ओर ले जा सकता है। आईसीएस + संस्करणों में इसका उपयोग करने के लिए स्वतंत्र महसूस करें।
वाहिद गदिरी

@ सिद्दांत धन्यवाद मैं अपने में छवियों को दोहराने GridViewऔर बदलने android:layout_heightऔर android:layout_widthमेरे लिए काम नहीं करने के कारण एक दिन का समय खर्च करता हूं। लेकिन ViewHolderमेरे लिए निश्चित दोहराई गई छवियों का उपयोग करते हुए मैं इस ट्यूटोरियल android-vogue.blogspot.com/2011/06/… के
निकोले पॉडोलनी

4

प्रश्न: एडेप्टर कॉल getView () manytimes? उत्तर: स्क्रॉलिंग पर लिस्टव्यू रेंडर रिफ्रेश होने के साथ-साथ यह अगले आगामी दृश्यों के साथ देखने वाला है, जिसके लिए एडॉप्टर को getView () कॉल करके विचार प्राप्त करने की आवश्यकता होती है।

प्रश्न: यदि fill_parent में listview चौड़ाई और ऊंचाई सेट की जाती है तो इसे कम क्यों कहा जाता है? उत्तर: क्योंकि श्रोता के पास स्क्रीन के लिए स्क्रीन क्षेत्र के लिए निश्चित आकार है, जो स्क्रीन पर विचारों को प्रस्तुत करने के लिए एक बार गणना करता है।

आशा है कि यह आपकी क्वेरी को हल कर देगा।


महान व्याख्या। लेकिन match_parent एक बेहतर विकल्प हो सकता है।
फटी

हां @ जोलो, यह एपीआई 2.4 / 3.0 से fill_parent के बजाय माचिस_परेंट का उपयोग करने की सिफारिश की गई है
jainain sharma

4

मुझे AutoCompleteTextView में ड्रॉपडाउन के साथ भी यही समस्या थी। मैं दो दिनों से समस्या से जूझ रहा था जब तक मैं यहां नहीं पहुंचता और आप मुझे इसका समाधान दिखाते हैं।

अगर मैं dropDownHeight = "match_parent" लिखता हूं तो समस्या ठीक हो जाती है। अब समस्या UI से संबंधित है (जब आपके पास एक आइटम ड्रॉपडाउन बहुत बड़ा है) लेकिन कई कॉल की समस्या (बहुत अधिक महत्वपूर्ण) तय हो गई है।

धन्यवाद!!


2

"प्रत्येक पंक्ति को तीन बार क्यों बुलाया जाता है?" क्योंकि जब आप सूची पर स्क्रॉल करते हैं और बेहतर कहने के लिए getView कहते हैं, तो यह तब कहा जाता है जब आपकी सूची के दृश्य की स्थिति बदल जाती है!


ठीक है, लेकिन दृश्य नहीं बदला है। गतिविधि शुरू होने पर स्क्रीन पर चार पंक्ति दृश्य होते हैं, और बिना स्क्रॉलिंग या किसी भी उपयोगकर्ता इनपुट के बिना मुझे प्रत्येक पंक्ति के लिए तीन getView कॉल मिलते हैं ...
edzillion

यह उत्तर गलत है। सही उत्तर यह है कि ** wra_content ** का उपयोग करने से भारी संख्या में कॉल प्राप्त होते हैं।
फटी

2

मुझे भी वही समस्या हो रही है। अगर मेरे पास fill_parent के लिए ऊँचाई सेट है, तो मुझे प्रति पंक्ति में "आमतौर पर" 2 कॉल मिलते हैं। लेकिन, यदि मैं अपने ListView की ऊंचाई को सटीक मान पर सेट करता हूं, तो 300dp पर कहते हैं, तो मुझे प्रति पंक्ति एक गेटवे कॉल बिल्कुल मिलता है।

तो, यह मुझे लगता है कि एकमात्र तरीका स्क्रीन की ऊंचाई निर्धारित करना है, फिर उस मान के लिए प्रोग्रामव्यू की ऊंचाई निर्धारित करें। मुझे यह पसंद नहीं है। मुझे उम्मीद है कि एक बेहतर तरीका है।


1
उसके लिए धन्यवाद। यह मज़ेदार है - इस सवाल ने महीनों से सुस्त चल रहे हैं कि पिछले कुछ हफ्तों में केवल कुछ टिप्पणियां दिखाई दी हैं। मैं अब इस परियोजना को नहीं कर रहा हूं, लेकिन जब से मेरे पास कुछ समय है मैं इसे एक कोशिश देने जा रहा हूं और फिर पुष्टि करने के लिए यहां वापस आऊंगा। एक बार फिर धन्यवाद।
edzillion

यहाँ भी, मुझे प्रति पंक्ति दो कॉल मिलते हैं। पंक्तियाँ 0,1,2,3 और फिर 100ms बाद में एक और 0,1,2,3 - जो कि पंक्तियों को देखा जाता है के बारे में आंकड़े इकट्ठा करते समय गधे में दर्द होता है
कोई कहीं

2

अभी भी आप जो के सभी (स्थापित करने के बाद के लिए heightके ListViewलिए match_parent) अटक (जैसे मैं था) कर रहे हैं:

आपको heightपैरेंट लेआउट को भी सेट करना होगा match_parent

नीचे उदाहरण देखें। LinearLayoutयहां माता पिता है:

<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/something" />

        <ListView
            android:id="@+id/friendsList"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>

1

यह शायद देर से आ रहा है लेकिन अगर आप layout_weightहमेशा सेट करने के लिए याद का उपयोग कर रहे हैंlayout_width="0dp"


0

मैं इस समाधान बनाया है, शायद सबसे अच्छा एक नहीं है, लेकिन काम करता है ...

//initialize control string
private String control_input = " ";

फिर =

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View gridview = convertView;

    // change input_array for the array you use
    if (!control_input.equals(input_array[position])) {
        control_input = input_array[position];

        //do your magic

    } 

    return gridview;
}

आशा करता हूँ की ये काम करेगा!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.