2012-03-15 12 views
9

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

मुझे एक अजीब समस्या आई है कि मुझे यकीन नहीं है कि कैसे काम करना है। मैंने यहां चारों ओर बहुत सी समस्याएं पढ़ी हैं, जैसे कि वे एक ही समस्या है जैसे वे हैं, लेकिन उनकी समस्याओं का समाधान यहां क्या हो रहा है, इस पर लागू नहीं होता है।

मेरे पास एक कस्टम सूची है जो एक अलग वर्ग का उपयोग करके सेट अप करें जो बेसएडाप्टर को विस्तारित करता है और एक व्यू धारक का उपयोग करता है (मैंने इसे कस्टम सूचीदृश्य के विभिन्न उदाहरणों को देखकर सेट किया है)। इसमें एक टेक्स्ट व्यू, एक बटन, एक प्रोग्रेस बार और एक छवि बटन है, और ये आइटम एक फ़ाइल डाउनलोड करने के लिए इस्तेमाल किए गए असिनकटास्क के आधार पर छुपा/बदला गया है।

जब मैं धीरे-धीरे सूची में स्क्रॉल करता हूं तो सब कुछ ठीक काम करता है। जब मैं सूची को तेजी से ऊपर/नीचे स्क्रॉल करता हूं, तो ऐसा लगता है कि सूची में कुछ कक्षों के विचार अन्य कोशिकाओं को फिर से सौंपे जाते हैं।

मैं अपने एडाप्टर कक्षा में मेरे "getView" विधि के शीर्ष में इस लाइन डाल:

@Override 
    public View getView(final int pos, View convertView, ViewGroup parent) 
    { 
     Log.i("ks3","getView called, position is " + pos); 

मैं अपने सूची में 7 आइटम, और उनमें से 6 स्क्रीन पर फिट है। जब वह पहली बार प्रदर्शित किया जाता है, मैं अपने लॉग में इस देखें:

getView called, position is 0 
getView called, position is 1 
getView called, position is 2 
getView called, position is 3 
getView called, position is 4 
getView called, position is 5 

जब मैं अगले आइटम पर धीरे-धीरे नीचे स्क्रॉल करें, यह अगले बाहर मुद्रित किया जाता है:

getView called, position is 6 

जब मैं वापस ऊपर स्क्रॉल इस, :

getView called, position is 0 

नीचे जा रहे हैं और ऊपर धीरे-धीरे इन परिणामों दोषरहित उत्पादन।

जब मैं आगे पीछे जल्दी से स्क्रॉल शुरू करते हैं, यह समय की एक गुच्छा इस संदेश को बाहर प्रिंट, ज्यादातर स्थिति के रूप में 6 और 0 दिखा रहा है, लेकिन कभी कभी मैं इन के साथ-साथ देखेंगे:

getView called, position is 1 
getView called, position is 5 

पदों 1 और 5 को कॉल नहीं किया जाना चाहिए, क्योंकि वे हमेशा स्क्रीन पर होते हैं। ऐसा लगता है जैसे GetView सब झुका हुआ है। उसी समय, जैसा कि मैंने पहले कहा था, मेरी सूची अजीब लगेगी। छवि बटन एक सेल को ऊपर या नीचे ले जाया जाएगा जहां वे नहीं होना चाहिए।

यदि मैं आसानी से स्क्रॉल करने के लिए वापस जाता हूं, तो मुझे स्थिति के लिए केवल 0 और 6 का दृश्य दिखाई देता है।

मुझे ईमानदारी से यह सुनिश्चित नहीं है कि इस के आसपास कैसे काम करें। मैंने सोचा कि शायद मैं सीमित कर सकता हूं कि आप सूची के माध्यम से कितनी तेजी से स्क्रॉल करने में सक्षम हैं, लेकिन काम करने वाली कुछ भी नहीं ढूंढ पाए हैं।

धन्यवाद!

संपादित करें: मैं इस प्रश्न के बारे में कुछ चीजें अपडेट करना चाहता था। सबसे पहले, सूची में Google वीडियो से यहां और यहां से एक टिप्पणी से, यह मेरे ध्यान में आया है कि अन्य दृश्यों के लिए getView को बुलाया जा सकता है, फिर मैंने कल्पना की कि यह माप के लिए क्या था, और इसलिए मुझे चिंतित नहीं होना चाहिए जो मैंने मूल रूप से सोचा था, वह मेरी समस्या का हिस्सा था (यह कि मैंने सोचा था कि getView को गलत स्थिति के साथ बुलाया जा रहा था)।

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

कि, इस तथ्य के साथ कि मैं getView के बाहर के विचारों को अद्यतन करता हूं और मैं NotifyDataSetChanged() को सूचित नहीं करता हूं; जो लोग एक साथ कुछ भद्दा सामान होने के कारण हैं।

+0

कहना मैं एक भी TextView के साथ एक item_view (लेआउट) है, तो एडाप्टर पालन होना चाहिए की सुविधा देता है जब तक आपकी कस्टम ListView कुछ फंकी नहीं कर रही है, यह रीसाइक्लिंग समस्या की तरह लगता है, अपना पूरा getView() कोड पोस्ट करें। – dmon

+0

यदि आपको अपने कोड में कोई त्रुटि नहीं मिलती है और आप हनीकॉम या ऊपर का उपयोग करते हैं तो आप अपनी सूची लेआउट के लिए हार्डवेयर त्वरण को अक्षम करने का प्रयास कर सकते हैं। हार्डवेयर त्वरण संभावित रूप से ऐसी त्रुटियों का कारण बन सकता है। – zapl

+1

यह एक रीसाइक्लिंग मुद्दे की तरह महसूस करता है। मैं सूची में Google वीडियो पर एक नज़र डालने जा रहा हूं और देखता हूं कि सूची दृश्य का उपयोग करने के तरीके के साथ कोई चमकदार समस्याएं हैं या नहीं। – Droidmon

उत्तर

13

आप सही हैं कि ListView स्क्रीन पर विभिन्न स्थानों पर विचारों का पुन: उपयोग कर रहा है। यह हर समय नए विचार आवंटित करके स्मृति उपयोग को उचित और तेज़ रखने का अनुकूलन है।

संभावना है कि आप LiewView गलत तरीके से उपयोग कर रहे हैं। this talk on how to properly use ListView देखो पूरी कहानी पाने के लिए है, लेकिन यहाँ है पर प्रकाश डाला:

  1. "स्थिति" एडाप्टर सूची में अपने डेटा के स्थान को दर्शाता है। यदि आपका एडाप्टर डेटा सरणी में है, तो यह उस सरणी में सूचकांक होगा।
  2. "आईडी" डेटा के मूल्य को ही संदर्भित करता है। यदि आपके पास नामों की एक सूची है और उनका सहारा लेना है, तो उनकी स्थिति बदल जाएगी, लेकिन उनकी आईडी नहीं होगी।
  3. "इंडेक्स" देखने योग्य स्क्रीन क्षेत्र के संबंध में एक दृश्य के सापेक्ष स्थान को संदर्भित करता है। आपको शायद इसकी आवश्यकता नहीं होगी।
  4. विचारों में हेरफेर मत (या उन्हें कैश करने के लिए प्रयास) अपने एडाप्टर के getView() विधि के बाहर या आप अजीब व्यवहार मिल जाएगा।
  5. यदि getView(int, View, ViewGroup) पर कॉल एक दृश्य उदाहरण प्रदान करता है, तो अपने क्षेत्र को पूरी तरह से नए विचारों को बढ़ाने के बजाय पॉप्युलेट करें। मान लें कि आपने सही ढंग से कार्यान्वित किया है, आपको हमेशा सही View टाइप करने के लिए सही तरीके से प्राप्त होगा।
  6. अपनी getView() विधि जितनी जल्दी हो सके उतनी जल्दी बनाएं, और केवल अन्य धागे पर भारी भारोत्तोलन करें।
  7. सिर्फ इसलिए कि getView() नामक कंटेनर का मतलब यह नहीं है कि डेटा प्रदर्शित किया जाएगा। ढांचे माप उद्देश्यों के लिए इनका उपयोग करता है। चूंकि काम को फेंक दिया जा सकता है, यह सुनिश्चित करने का एक और कारण है कि getView() उतना तेज़ है जितना आप इसे बना सकते हैं।
  8. कुछ अपने डेटा जो आप स्क्रीन पर दिखाने की जरूरत के लिए होता है, कहते हैं कि आपका डाउनलोड पूरा हो, कि जब आप notifyDataSetChanged() फोन है। सीधे विचारों के साथ परेशान न हों, जब वे फिर से खींचे जाएंगे तो वे अगले यूआई लूप पर आबादी लेंगे।

सिर्फ दोबारा काम एक ListView कि भोलेपन से लागू किया गया था, मैं अपने दर्द महसूस कुछ दिनों के खर्च करने के बाद। परिणाम इसके लायक हैं, यद्यपि!

+2

Argyle, लिंक के लिए बहुत बहुत धन्यवाद। मुझे सूची दृश्य कैसे काम करता है, इस बारे में पर्याप्त जानकारी नहीं है, और मैं स्वीकार करूंगा कि मैं getView के बाहर के विचारों को अपडेट कर रहा हूं, इसलिए मुझे यह पता लगाना होगा किडेटाडेट चेंज() को सूचित करने के साथ कैसे काम करना है। – Droidmon

+0

सर pls मेरा दर्द महसूस करते हैं! क्या आप इस प्रश्न का उत्तर दे सकते हैं http://stackoverflow.com/questions/22451081/how-to-track-the-position-of-item-while-scrolling-in-a-long-listview –

+0

मेरे पास कुछ मध्य-भारी है प्रत्येक आइटम पर प्रसंस्करण और गतिशील आकार जोड़ें और मुझे इसके लिए getview() में बस जगह मिल जाएगी। तो जब मैं इसे स्थानांतरित कर सकता हूं तो आपके बिंदु पर निर्भर करता है? – Kenji

0

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

+0

आह, ठीक है, यह जानना अच्छा है, मुझे खुशी है कि यह नहीं है, या कम से कम समस्या का कारण बनना नहीं चाहिए। – Droidmon

4

हमेशा इस दृष्टिकोण का उपयोग गेटव्यू में करें: कन्वर्टव्यू = inflater.inflate (R.layout.listinflate, पैरेंट, झूठा);

और अपनी गतिविधि जाने onScrollListener लागू करता है और उपयोगकर्ता अपने सूचीदृश्य एडाप्टर सूचित सही ढंग से आइटम अपडेट करने के प्रयासों को लेने कोई बात नहीं करने के लिए टूट पड़नेवाला जाता है। और उपयोगकर्ता कोई और अधिक टूट पड़नेवाला है जब getView में डेटा उपलब्ध कराने के बारे में देखभाल करने के लिए एडाप्टर बताओ।

इससे मेरी सभी समस्याओं का समाधान हुआ। और एक और चीज सूची दृश्य ऊंचाई में wrap_content का उपयोग नहीं करती है।इसमें भी smoothscroll झूठी सेट करें। एडाप्टर में मैं getView विधि में पृष्ठभूमि का रंग बदल रहा था, लेकिन कभी कभी सूचीदृश्य था "RECICLYNG" दृश्य (गलत पृष्ठभूमि हो रही):

+0

wrap_content का उपयोग नहीं करने में मेरी मदद मिली – pkacprzak

1

मैं एक ही समस्या थी। मैं बस प्रत्येक

if(...){changeBackground}

को "और" डाल हल मैं

else {restore default background}

जोड़ा और फिर यह रिकॉर्ड के लिए सुचारू रूप से

+0

मैन, आप कमाल हैं! मैंने अपनी समस्या का पता लगाने में मेरी सुबह का एक अच्छा हिस्सा बिताया। आपका बहुत बहुत धन्यवाद! –

+0

कोई समस्या नहीं! जानकर ख़ुशी हुई की! ;) – Mark

0

काम किया है और @Mark

के जवाब का विस्तार

Android अगला कार्य करता है। मान लें कि मेरे पास 100 तत्वों की एक सूची है। आप जो व्हीएम लोड कर रहे हैं, उदाहरण के लिए तत्व 0,1,2,3 ... से 10 के लिए गेटव्यू कहा जाता है। और यदि हम जारी रखते हैं, तो अगली स्थिति 11 होगी। हालांकि, स्थिति 11 स्थिति 0 की तुलना में एक ही दृश्य को पुन: उपयोग करती है। इसलिए, स्थिति 11 के लिए दृश्य मौजूद है लेकिन इसमें गलत मान (0 मान) है।

उत्तर: यदि दृश्य शून्य है या नहीं, तो डेटा संशोधित करें। यदि दृश्य शून्य है, तो दृश्य के मानों को डिफ्लेट और संशोधित करें। यदि नहीं, तो दृश्य के मान संशोधित करें।

सही संस्करण:

public class XXXAdapter extends ArrayAdapter<XXX> {.... 
@NonNull 
@Override 
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { 
    if (convertView==null) { 
     LayoutInflater inflater = LayoutInflater.from(this.getContext()); 
     convertView = inflater.inflate(R.layout.**itemofthelayout**, parent, false); 
    } 
    ***Object** item=this.getItem(position); 
    TextView txt= (TextView) convertView.findViewById(R.id.**idsometextviewinsidelayout**); 
    txt.setText(String.valueOf(position)); 
    return convertView; 
    // return super.getView(position, convertView, parent); 
} 

गलत संस्करण:

public class XXXAdapter extends ArrayAdapter<XXX> {.... 
@NonNull 
@Override 
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { 
    if (convertView==null) { 
     LayoutInflater inflater = LayoutInflater.from(this.getContext()); 
     convertView = inflater.inflate(R.layout.**itemofthelayout**, parent, false); 
     ***Object** item=this.getItem(position); 
     TextView txt= (TextView) convertView.findViewById(R.id.**idsometextviewinsidelayout**); 
     txt.setText(String.valueOf(position)); 
     return convertView; 
     // return super.getView(position, convertView, parent); 
    } 
} 
संबंधित मुद्दे

 संबंधित मुद्दे