कैसे ListView के रीसाइक्लिंग तंत्र काम करता है


146

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


public View getView(int position, View convertView, ViewGroup parent) {
        if(convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            convertView = inflater.inflate(R.layout.day_view_item, parent, false);
        }
        Log.d("DayViewActivity", "Position is: "+position);
        ((TextView)convertView.findViewById(R.id.day_hour_side)).setText(array[position]);
        LinearLayout layout = (LinearLayout)convertView.findViewById(R.id.day_event_layout);

        //layout.addView(new EventFrame(parent.getContext()));

        TextView create = new TextView(DayViewActivity.this);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 62, getResources().getDisplayMetrics()), 1.0f);
        params.topMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
        params.bottomMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
        create.setLayoutParams(params);
        create.setBackgroundColor(Color.BLUE);
        create.setText("Test"); 
        //the following is my original LinearLayout.LayoutParams for correctly setting the TextView Height
        //new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, getResources().getDisplayMetrics()), 1.0f)   
        if(position == 0) {
            Log.d("DayViewActivity", "This should only be running when position is 0. The position is: "+position);
            layout.addView(create);
        }

        return convertView;
    }

}

समस्या तब होती है जब मैं स्क्रॉल करता हूं, यह होता है, न कि स्थिति 0 पर ... स्थिति 6 और स्थिति 8 जैसी दिखती है, साथ ही यह दो स्थिति 8 में रखती है। अब मैं अभी भी ListView और GridView का उपयोग करके हैंग होने की कोशिश कर रहा हूं इसलिए समझ में नहीं आ रहा है कि ऐसा क्यों हो रहा है। एक मुख्य कारण जो मैं यह सवाल कर रहा हूं, वह है दूसरों की मदद करना, जो शायद ListView और GridView के पुनर्चक्रण दृश्य के बारे में नहीं जानते हैं, या जिस तरह से यह लेख इसे लागू करता है, ScrapView तंत्र।

यहाँ छवि विवरण दर्ज करें

बाद में संपादित करें

एक Google IO टॉक से लिंक जोड़ना जो मूल रूप से आप सभी को यह समझने की आवश्यकता है कि ListView कैसे काम करता है। लिंक टिप्पणियों पर मृत था। तो उस लिंक को अपडेट करने के लिए user3427079 काफी अच्छा था। यहाँ यह आसान पहुँच के लिए है।


हाहा, उस लिंक के लिए धन्यवाद। यह अब देखना शुरू किया :)
एंडी

आपने पिछले प्रश्न से कोड नमूने को पूरी तरह से लागू नहीं किया है। विचार यह है कि आपके द्वारा हमेशा अन्य पंक्तियों (आपके मामले में स्थिति 0) के लिए किए गए परिवर्तनों को वापस करने के लिए आपके पास कोड का एक टुकड़ा होना चाहिए ।
लुक्सप्रोग

अच्छी तरह से मैं समझता हूँ कि @Luksprog लेकिन क्या यह समझाता है कि इसके दृश्य अन्य पदों पर भी क्यों हैं? यदि कुछ भी हो, तो मुझे उम्मीद है कि केवल 0 स्थान डुप्लिकेट दृश्य होंगे। Idk, अभी भी यह समझने में परेशानी हो रही है कि कैसे ListView इस सामान को बांध रहा है: /
एंडी

1
पुनर्चक्रण का अर्थ है कि वह पंक्ति दृश्य जो केवल गायब हो गया था (उदाहरण के लिए स्थिति 0, एक पंक्ति को नीचे स्क्रॉल करने के बाद) स्क्रीन से बाद में उपयोग किया जा सकता है जब ListViewनई पंक्ति को दिखाने की आवश्यकता होती है (जैसे नीचे / ऊपर स्क्रॉल करना जारी रखें)। समस्या यह है कि जो दृश्य अभी गायब हो गया है और जिसका उपयोग भविष्य में आवश्यक पदों पर किया जाएगा TextView, उसमें पहले से ही जोड़ा गया है, यह समस्या है। इसे हल करने के लिए आपको इसे getViewविधि में निकालना होगा यदि getViewविधि को किसी अन्य स्थिति के लिए कहा जाता है 0
लुक्सप्रोग

2
शीर्ष पोस्ट की लिंक मृत है, मुझे लगता है कि यह है? youtube.com/watch?v=N6YdwzAvwOA
G_V

जवाबों:


330

प्रारंभ में, मैं लिस्टव्यू रिसाइकिलिंग और कन्वर्टव्यू यूसेज मैकेनिज्म से भी अनभिज्ञ था, लेकिन एक पूरे दिन के शोध के बाद, मैं android.amberfog से एक छवि का संदर्भ देकर सूची दृश्य के तंत्र को बहुत अधिक समझता हूं। यहाँ छवि विवरण दर्ज करें

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

System.out.println("getview:"+position+" "+convertView);

अपने अंदर

public View getView(final int position, View convertView, ViewGroup parent)
{
    System.out.println("getview:"+position+" "+convertView);
    ViewHolder holder;
    View row=convertView;
    if(row==null)
    {
        LayoutInflater inflater=((Activity)context).getLayoutInflater();
        row=inflater.inflate(layoutResourceId, parent,false);
        
        holder=new PakistaniDrama();
        holder.tvDramaName=(TextView)row.findViewById(R.id.dramaName);
        holder.cbCheck=(CheckBox)row.findViewById(R.id.checkBox);
        
        row.setTag(holder);
        
    }
    else
    {
        holder=(PakistaniDrama)row.getTag();
    }
            holder.tvDramaName.setText(dramaList.get(position).getDramaName());
    holder.cbCheck.setChecked(checks.get(position));
            return row;
    }

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

अब जब आप ऊपर / नीचे स्क्रॉल करते हैं, तो आपकी सूची एक नया दृश्य बनाने वाली नहीं है, यह उस दृश्य का उपयोग करेगी जो आपके रिसाइक्लर में है। अपने Logcat में आप देखेंगे कि 'ConvertView' शून्य नहीं है, इसका कारण यह है कि आपके नए आइटम 8 को कन्वर्टव्यू का उपयोग करके तैयार किया जाएगा, अर्थात, मूल रूप से यह रिसाइकलर से आइटम 1 दृश्य लेता है और इसके स्थान पर आइटम 8 को फुलाता है, और आप देख सकते हैं मेरे कोड में। यदि आपके पास एक चेकबॉक्स था और यदि आप इसे स्थिति 0 पर चेक करते हैं (मान लें कि आइटम 1 में एक चेकबॉक्स था और आपने इसे चेक किया था) तो जब आप नीचे स्क्रॉल करेंगे तो आपको आइटम 8 चेकबॉक्स पहले से ही चेक होता हुआ दिखाई देगा, यही कारण है कि सूची दृश्य में समान दृश्य का उपयोग किया जा रहा है, प्रदर्शन अनुकूलन के कारण आपके लिए कोई नया निर्माण नहीं हो रहा है।

जरुरी चीजें

1 है । कभी सेट layout_heightऔर layout_widthकरने के लिए अपने सूचीदृश्य के wrap_contentरूप में getView()देखे जाने की ऊंचाई मापने सूची दृश्य में तैयार होने में कुछ बच्चे पाने के लिए अपने एडाप्टर के लिए बाध्य करेगा और convertview भी सूची लौटने की तरह कुछ अनपेक्षित व्यवहार का कारण बन सकती है scrolled.always का उपयोग match_parentया निर्धारित चौड़ाई ऊंचाई।

। आप अपनी सूची में देख सकते हैं और प्रश्न हो सकता है के बाद कुछ लेआउट या दृश्य का उपयोग करना चाहते हैं तो आपके मन में आया था अगर मैं सेट layout_heightकरने के लिए fill_parentसूची दृश्य के बाद दृश्य नहीं दिखाया जाएगा के रूप में यह है, स्क्रीन नीचे चला जाता है तो इसके बेहतर एक के अंदर अपने सूचीदृश्य डाल करने के लिए लेआउट। उदाहरण के लिए रैखिक लेआउट और अपनी आवश्यकता के अनुसार उस लेआउट की ऊंचाई और चौड़ाई सेट करें और अपने लेआउट के अनुसार अपनी सूची की ऊंचाई और चौड़ाई विशेषता बनाएं (जैसे यदि आपका लेआउट चौड़ाई 320 है और ऊंचाई 280 है) तो आपकी सूची समान ऊंचाई और चौड़ाई होनी चाहिए। यह बताएगा कि देखे जाने की सटीक ऊँचाई और चौड़ाई का getView () और getView () बार-बार कुछ यादृच्छिक पंक्तियों को नहीं बुलाएगा, और अन्य समस्याएँ जैसे वापसी स्क्रॉल बदलने से पहले ही दृश्य परिवर्तित करना होगा, मेरे पास परीक्षण है यह अपने आप में, जब तक कि मेरी सूची दृश्य के अंदर नहीं थी, यह भी देखने की कॉल को दोहराने और दृश्य को परिवर्तित करने जैसी समस्याएं थीं, जैसे कि LinearLayout के अंदर Listview को मेरे लिए जादू की तरह काम किया। (पता नहीं क्यों)

01-01 14:49:36.606: I/System.out(13871): getview 0 null
01-01 14:49:36.636: I/System.out(13871): getview 0 android.widget.RelativeLayout@406082c0
01-01 14:49:36.636: I/System.out(13871): getview 1 android.widget.RelativeLayout@406082c0
01-01 14:49:36.646: I/System.out(13871): getview 2 android.widget.RelativeLayout@406082c0
01-01 14:49:36.646: I/System.out(13871): getview 3 android.widget.RelativeLayout@406082c0
01-01 14:49:36.656: I/System.out(13871): getview 4 android.widget.RelativeLayout@406082c0
01-01 14:49:36.666: I/System.out(13871): getview 5 android.widget.RelativeLayout@406082c0
01-01 14:49:36.666: I/System.out(13871): getview 0 android.widget.RelativeLayout@406082c0
01-01 14:49:36.696: I/System.out(13871): getview 0 android.widget.RelativeLayout@406082c0
01-01 14:49:36.706: I/System.out(13871): getview 1 null
01-01 14:49:36.736: I/System.out(13871): getview 2 null
01-01 14:49:36.756: I/System.out(13871): getview 3 null
01-01 14:49:36.776: I/System.out(13871): getview 4 null

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


36
"मुझे पता है कि समझाने में यह अच्छा नहीं है" >>> इस जवाब पर +37 वोट बताते हैं कि आपने मुझे समझाने में एक उत्कृष्ट काम किया। कृपया अपना ज्ञान साझा करते रहें! ;)
2

1
महान जवाब राज जी +1 मुझसे .. :)
एहसान सज्जाद

2
छवि के लिए धन्यवाद। एंड्रॉइड के साथ शुरू होने पर लिस्ट व्यू के साथ बहुत सारी परेशानियां होने के बाद, मैं पहले से ही इसके बारे में बहुत संघर्ष करने के बाद रीसाइक्लिंग सिद्धांत को जानता था। फिर भी, इस तस्वीर और वाक्य को लिया: if you had a checkbox and if you check it at position 0(let say item1 has also a checkbox and you checked it) so when you scroll down you will see item 8 checkbox is already checked,this is why listview is re using the same view not creating a new for you due to performance optimization.मेरी गलती का एहसास करने के लिए। Android ListView रीसाइक्लिंग के बारे में सबसे अच्छी पोस्ट मैं भर में आया!
केविन क्रूज़सेन

1
@MuhammadBabar हां, मैंने प्रश्न पोस्ट किया है: stackoverflow.com/q/30122027/1318946
प्रतीक बुटानी

1
@MuhammadBabar कमाल का स्पष्टीकरण आदमी! यह मेरा समय बचाता है। बस जानना चाहते हैं, क्या यह RecyclerViewभी एक ही तंत्र पर काम करता है? मेरे प्रश्न में stackoverflow.com/questions/47897770/… , मुझे पता है कि कार्य के साथ शांत असंभव है listView। क्या मुझे कोशिश करनी चाहिए recyclerView?
शंभू

8

ध्यान रखें, धारक पैटर्न में, यदि आप अपने धारक वस्तु में आसन सेट करते हैं, तो आपको इसे हर बार सेट करना चाहिए, उदाहरण के लिए:

@Override
public final View getView(int position, View view, ViewGroup parent) {
    Holder holder = null;
    if (view == null) {
        LayoutInflater inflater = (LayoutInflater) App.getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(getContainerView(), parent, false);
        holder = getHolder(position, view, parent);
        holder.setTag(tag);
        view.setTag(holder);
    } else {
        holder = (Holder) view.getTag();
    }
    holder.position = position;
    draw(holder);
    return holder.getView();
}

यह एक सार वर्ग से एक उदाहरण है, जहां

getHolder(position, view, parent);

के लिए सभी सेटिंग ऑपरेशन करता है

ImageViews, TextViews, etc..

1
ध्यान नहीं दिया कि यह सब समय मैं कर रहा था। parent.setTag(holder);सही तरीके के बजाय जो है,view.setTag(holder);
ArtiomLK

2

होल्डर पैटर्न का उपयोग करके आप जो चाहें हासिल कर सकते हैं:

आप इस पैटर्न का विवरण यहां पा सकते हैं:

सूची दृश्य का पुनरावर्तन तब होता है जब आप स्क्रीन को नीचे स्क्रॉल करते हैं और ऊपर सूची दृश्य आइटम छिपे होते हैं। नई सूची दृश्य आइटम दिखाने के लिए उनका पुन: उपयोग किया जाता है।

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