2012-06-26 12 views
5

विचार यह है कि किसी आइटम पर क्लिक करने के बाद आइटमों की एक सूची होनी चाहिए, एक प्रगतिबार धीरे-धीरे भर जाएगा क्योंकि कार्य पूरा हो जाएगा। उदाहरण के लिए, प्रत्येक के द्वारा एक डाउनलोड बटन के साथ, फ़ाइलों की एक सूची तस्वीर। जब डाउनलोड बटन क्लिक किया जाता है, तो फ़ाइल पृष्ठभूमि में डाउनलोड की जाती है और एक प्रगति पट्टी भर जाती है यह दर्शाती है कि फाइल को पूरा करने के करीब कितना करीब है।एक सूची दृश्य/ऑनक्लिक पर प्रोग्रेसबार जोड़ना एक बार कहा जाता है

इसे पूरा करने के लिए, मैं एक AsyncTask बना देता हूं जो कभी-कभी अधिसूचनाओं को सूचित करने के लिए एडाप्टर पर डेटाटाट को सूचित करता है। हालांकि यह एक बटन क्लिक करने के बाद काम करता है, जब तक AsyncTask पूरा नहीं हो जाता है, मैं ListView में अन्य बटन क्लिक करने में असमर्थ हूं। क्या कोई मुझे बता सकता है कि मैं क्या गलत कर रहा हूं?

मैं इसे आइस क्रीम सैंडविच पर एमुलेटर (x86) पर चला रहा हूं।

:

class DownloadItem { 
    public String name;  // Name of the file being downloaded 
    public Integer progress; // How much is downloaded so far 
    public Integer length; // Size of the file 
} 

मैं तो एक ArrayAdapter कि ListView के लिए DownloadItem की एक सूची adapts है:

मैं एक डाउनलोड की प्रगति (नीचे दिए गए कोड संक्षिप्तता के लिए सरल है) का प्रतिनिधित्व करने के लिए एक DownloadItem है

अभी तक, बहुत अच्छा - यह सूची को उचित रूप से प्रस्तुत करता है।

class DownloadActivity extends Activity { 
    //... 
    public void onDownloadButtonClick(View view) { 
     DownloadItem item = (DownloadInfo)view.getTag(); 
     DownloadArrayAdapter adapter = (DownloadArrayAdapter) view.getAdapter(); 
     new DownloadTask(adapter, item).execute(); 
     //new DownloadTask(adapter, item).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) 
    } 
} 

मैं भी बस पर अमल के रूप में executeOnExecutor के साथ इस की कोशिश की है, लेकिन कोई भाग्य के साथ: मेरे गतिविधि में, मैं onClickListener है। डाउनलोड टास्क है:

class DownloadTask extends AsyncTask<Void, Integer, Void> { 
    ArrayAdapter<?> mAdapter; 
    DownloadItem mItem; 

    public DownloadTask(ArrayAdapter<?> adapter, DownloadItem item) { 
     mItem = item; 
    } 

    //Dummy implementation 
    @Override 
    public Void doInBackground(Void ... params) { 
     for(int i=0; i<mItem.length; ++i) { 
      Thread.sleep(10); publishProgress(i); 
     } 
     return null; 
    } 

    @Override 
    public void onProgressUpdate(Integer ... values) { 
     mItem.progress = values[0]; 
     mAdapter.notifyDataSetChanged(); 
    } 
} 

यह काम करता है - लगभग। जब मैं ऐसा करता हूं, तो एक बटन पर क्लिक करने के बाद, प्रोग्रेसबार सामान्य के रूप में अपडेट होता है - लेकिन जब तक AsyncTask रिटर्न नहीं होता तब तक मैं ListView में अन्य बटन क्लिक नहीं कर सकता। यही है, onDownloadButtonClick कभी नहीं कहा जाता है। अगर मैं onProgressUpdate फ़ंक्शन से mAdapter.notifyDataSetChanged() कॉल को हटा देता हूं, तो कई कार्यों को एक साथ अपडेट किया जाता है, लेकिन निश्चित रूप से, सूची को अमान्य नहीं किया गया है और इसलिए मुझे परिवर्तन देखने के लिए चारों ओर स्क्रॉल करना होगा।

मैं क्या गलत कर रहा हूं, और मैं इसे कैसे ठीक कर सकता हूं?

संपादित करें: मैंने इसके साथ कुछ और खेला, और ऐसा लगता है कि कॉलिंग अधिसूचना की आवृत्तिडेटाट चेंज प्रभावित करती है कि ऑनक्लिक कहलाया जा रहा है या बस खो रहा है या नहीं। उपर्युक्त कोड के साथ, बेतरतीब ढंग से क्लिक करके मैं कभी-कभी शुरू करने के लिए दूसरी डाउनलोड बार प्राप्त कर सकता हूं। अगर मैं थ्रेड बढ़ाता हूं। 2000 की तरह कुछ बड़ा सो जाओ, सूची मूल रूप से अपेक्षित रूप में काम करती है।

तो नया सवाल - प्रोग्रेसबार को आसानी से अपडेट करने के लिए कैसे प्राप्त किया जा सकता है जबकि क्लिक करने से क्लिक करें?

संपादित करें # 2:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    View row = convertView; 
    if(row == null) { 
     // Inflate 
     Log.d(TAG, "Starting XML inflation"); 
     LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     row = inflater.inflate(R.layout.download_list_item, parent, false); 
     Log.d(TAG, "Finished XML inflation"); 
    } 

    final DownloadItem item = mItems.get(position); 

    ProgressBar downloadProgressBar = (ProgressBar) row.findViewById(R.id.downloadProgressBar); 
    Button downloadButton = (Button) row.findViewById(R.id.downloadButton); 

    downloadButton.setTag(item); 
    downloadProgressBar.setMax(item.length); 
    downloadProgressBar.setProgress(item.progress); 

    downloadButton.setOnClickListener(new View.OnClickListener() { 

     @Override 
     public void onClick(View v) { 
      new DownloadTask(DownloadArrayAdapter.this, item).execute(); 
     } 
    }); 

    return row; 
} 
+1

यह आप सूची दृश्य का उपयोग लगता है? यदि ऐसा है, और यदि आपके पास समय है, तो मुझे लगता है कि यह देखना उचित है: [Google I/O 2010 - सूची दृश्य] (http://www.youtube.com/watch?v=wDBM6wVEO70)। एक सुझाव: आप 'थ्रेड.sleep (800)' (उदाहरण के लिए) का उपयोग कर सकते हैं, '10' आवश्यक नहीं है। –

+1

आप क्लिक श्रोता कहाँ सेट करते हैं? आप इसे डमी कोड में याद करते हैं। – reTs

+0

@reTS: मैंने इसे XML में सेट किया है, एंड्रॉइड के साथ: बटन के लिए ऑनक्लिक पैरामीटर। हैंडलर निश्चित रूप से कहा जा रहा है - वैसे भी, वैसे भी। हालांकि प्रश्न में मेरा संपादन देखें। – mindvirus

उत्तर

5
+0

शानदार प्रदर्शन के लिए +1। चियर्स !!!! – skygeek

+0

हाय .... आपका कोड मेरे लिए बहुत मददगार था ... लेकिन मुझे एक समस्या है। जब मैं एक गतिविधि में अपना कोड चलाता हूं, तो यह बहुत अच्छा काम करता है। जब मैं एक टुकड़े में अपना कोड चलाता हूं, तो मुझे प्रगति बार ऑब्जेक्ट शून्य मिलता है। ऐसा क्यों है? –

+0

यदि आप एक या दो अन्य प्रगति पर हैं (पूर्व के लिए डॉउलोड) जब कोई आइटम हटाते हैं तो यह क्या होता है? क्योंकि मैं कोशिश करता हूं, लेकिन जब मैं कोई आइटम हटाता हूं, प्रोग्रेसबार बग। – Cocorico

1

आप अनुकूलक अपने आप में आइटम डाउनलोड करने के लिए निम्नलिखित की तरह क्लिक श्रोता सेट करने का प्रयास किया था: मैं अपने GitHub खाते में इस समस्या के साथ एक नमूना परियोजना धकेल दिया यह पता लगाया है।

सूचित करने के बजायडेटाट चेंज(), मैंने DownloadItem ऑब्जेक्ट में प्रत्येक प्रोग्रेसबार का संदर्भ संग्रहीत किया। फिर, ListView के माध्यम से स्क्रॉल करते समय, जब पुराने ऑब्जेक्ट को कन्वर्ट व्यू के रूप में पास किया गया था, तो मैंने प्रोग्रेसबार को पुराने DownloadInfo से हटा दिया और इसे नए पर रखा।

इस प्रकार, मेरी सरणी एडाप्टर के लिए getView तो बन गया:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    View row = convertView; 
    final DownloadInfo info = getItem(position); 
    // We need to set the convertView's progressBar to null. 

    ViewHolder holder = null; 

    if(null == row) { 
     LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     row = inflater.inflate(R.layout.file_download_row, parent, false); 

     holder = new ViewHolder(); 
     holder.textView = (TextView) row.findViewById(R.id.downloadFileName); 
     holder.progressBar = (ProgressBar) row.findViewById(R.id.downloadProgressBar); 
     holder.button = (Button)row.findViewById(R.id.downloadButton); 
     holder.info = info; 

     row.setTag(holder); 
    } else { 
     holder = (ViewHolder) row.getTag(); 

     holder.info.setProgressBar(null); 
     holder.info = info; 
     holder.info.setProgressBar(holder.progressBar); 
    } 

    holder.textView.setText(info.getFilename()); 
    holder.progressBar.setProgress(info.getProgress()); 
    holder.progressBar.setMax(info.getFileSize()); 
    info.setProgressBar(holder.progressBar); 

    holder.button.setEnabled(info.getDownloadState() == DownloadState.NOT_STARTED); 
    final Button button = holder.button; 
    holder.button.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
     info.setDownloadState(DownloadState.QUEUED); 
     button.setEnabled(false); 
     button.invalidate(); 
     FileDownloadTask task = new FileDownloadTask(info); 
     task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
     } 
    }); 
    return row; 
    } 

डाउनलोड AsyncTask तो, प्रगति बार पर प्रगति कायम होगी अगर यह रिक्त नहीं था, और इस उम्मीद के रूप में काम किया।

मैं GitHub के लिए सही कोड अपलोड किया है, तो आप इसे यहाँ देख सकते हैं: https://github.com/mdkess/ProgressBarListView

+0

हां, उसने कोई अच्छा काम नहीं किया - यह ऑनक्लिक तक भी नहीं पहुंच रहा है। मुझे लगता है कि इसे अधिसूचना कॉल करने के साथ करना हैडेटासेट बहुत बार बदल दिया गया है, इसलिए मैं अब वास्तविक प्रगति पट्टी का संदर्भ रखने के साथ प्रयोग कर रहा हूं। अच्छा विचार, यद्यपि। (वैसे, मैंने तुम्हें कम नहीं किया)। – mindvirus

+0

धन्यवाद। कभी मत सोचो कि किसने मुझे वोट दिया। दरअसल, मैंने आपके प्रश्न को सही ढंग से नहीं पढ़ा। मैंने सोचा, आप पंक्ति दृश्य में टैग सेट कर रहे हैं .. लेकिन आपने बटन डाउनलोड करने के लिए टैग सेट किया है .. इसलिए मैंने आपको यह समाधान दिया .. हां, प्रगति पट्टी के संदर्भ में गुजरना और प्रगति पट्टी को अपडेट करना सीधे काम करना चाहिए .. बीटीडब्ल्यू आपने सवाल पूछा अच्छा तरीका और मैं आपके कार्यान्वयन को भी पसंद करता हूं :-) .. – Veer

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