2011-06-05 7 views
10

आइए कहें कि मैं ArrayAdapter का विस्तार करता हूं और उस कोड में जहां मैं getView(int i, View v, ViewGroup g) ओवरराइड कर रहा हूं, मैं वर्तमान आइटम को getItem(i) का उपयोग कर पुनर्प्राप्त करता हूं। क्या मुझे यकीन है कि getItem(i) एक आइटम लौटाएगा भले ही अन्य धागे उसी ArrayAdapter में हेरफेर करें?एंड्रॉइड में ArrayAdapter थ्रेड सुरक्षित है? यदि नहीं, तो इसे धागा सुरक्षित बनाने के लिए मैं क्या कर सकता हूं?

मुझे यकीन नहीं है, लेकिन मुझे लगता है कि जवाब नहीं है। यदि ऐसा है, तो आप सुझाव देते हैं कि मैं इसे थ्रेड-सुरक्षित बनाने के लिए करता हूं?

उत्तर

27

यह ArrayAdapter थ्रेड सुरक्षित होने की बात नहीं है। ListView और ऐसे अन्य UI विजेट जो एडाप्टर के साथ काम करते हैं, एडाप्टर की सामग्री को अप्रत्याशित रूप से बदलने की अनुमति नहीं देते हैं। और यह अन्य धागे के कारण सिर्फ इतना है - आपको सूची दृश्य को आपके द्वारा किए गए परिवर्तन के बारे में बताने की आवश्यकता है, इससे पहले कि आप अपने एडाप्टर से बातचीत करने का प्रयास करें।

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

यदि आप अपनी सामग्री को संशोधित करने के लिए एपीआई का उपयोग करते हैं तो ऐरे एडाप्टर के विशिष्ट मामले में यह परिवर्तन के बारे में सूची दृश्य को बताने का ख्याल रखेगा। हालांकि आप मुख्य धागे पर ऐसे परिवर्तन कर सकते हैं, यह सुनिश्चित करने के लिए कि सूची दृश्य उस बिंदु के बीच एडाप्टर तक पहुंचने का प्रयास नहीं करता है जहां आपका परिवर्तन किया गया है और सूची दृश्य उस परिवर्तन के बारे में बताया गया है।

यदि आप केवल ऐरेएडाप्टर (कुछ आइटम जोड़ना और निकालना) में सरल परिवर्तन कर रहे हैं, तो आप ठीक होंगे लेकिन आपको इन्हें मुख्य धागे पर करना होगा।

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

इन जटिल परिस्थितियों में एडाप्टर अपडेट का सामान्य तरीका यह है कि एक पृष्ठभूमि धागा नए डेटा सेट उत्पन्न करता है, और एक बार जब यह उपलब्ध होता है तो मुख्य धागे पर इसे अधिसूचना में एडाप्टर में बदल दिया जाता है जिसे सूचित करने के लिए कॉल किया जाता है DataSetChanged() ListView को यह जानने के लिए कि डेटा बदल गया है।

तो मान लें कि आप कुछ डेटा दिखा रहे हैं जो MyItem ऑब्जेक्ट्स की एक सरणी है।एक नाटक सरणी में अपने डेटा रखें:

ArrayList<MyItem> 

BaseAdapter का एक उपवर्ग है कि इस सूची से पता चलता लागू:

class MyAdapter extends BaseAdapter<MyItem> { 
    ArrayList<MyItem> mItems; 

    public int getCount() { 
     return mItems != null ? mItems.size() : 0; 
    } 

    public MyItem getItem(int position) { 
     return mItems.get(i); 
    } 

    ... 
} 

और अब यहां एक समारोह आप एडाप्टर दूसरे से कहा जा सकता है पर लागू कर सकता है एक नया डेटा दिखाया जा करने के लिए सेट प्रदान करने के लिए सूत्र:

final Handler mHandler = new Handler(); 

    void setDataFromAnyThread(final ArrayList<MyItem> newData) { 
     // Enqueue work on mHandler to change the data on 
     // the main thread. 
     mHandler.post(new Runnable() { 
       @Override 
       public void run() { 
        mItems = newData; 
        notifyDataSetChanged(); 
       } 
      }); 
    } 
बेशक

आप AsyncTask उपयोग कर रहे हैं यह पहले से ही है कि प्रदर्शन करने के लिए एक सुविधाजनक सुविधा है अपने डेटा पीढ़ी करने के लिए मुख्य धागे पर वापस काम करें। इसी प्रकार आप पृष्ठभूमि में पीढ़ी की देखभाल करने के लिए नई लोडर सुविधा का उपयोग कर सकते हैं।

और यदि आप अभी भी अपने कार्य में ArrayAdapter का उपयोग करना चाहते हैं, तो आप वर्तमान डेटा को साफ़ करके और खाली डेटा को नए एडाप्टर में जोड़कर ऐसा कर सकते हैं। यह सिर्फ अधिक उपर है जो वास्तव में आपको कुछ भी हासिल नहीं करता है।

4

ऐरे एडाप्टर थ्रेड सुरक्षित नहीं है। मैंने समवर्ती मुद्दों के कारण इसे दुर्घटनाग्रस्त देखा है। सरणी एडाप्टर केवल आपके सरणी को मुख्य (जीयूआई) थ्रेड पर एक दृश्य पर अनुवाद करेगा। इसलिए यदि आप मुख्य धागे पर केवल सरणी (जोड़ या हटाएं) को बदलने के लिए सावधान हैं तो आप सुनिश्चित कर सकते हैं कि यह केवल 1 थ्रेड पर ही चलता है।

+0

अच्छा, मेरी समस्या हल हो गई। धन्यवाद – 2red13

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