Buradaki fikir, bir öğeyi tıkladıktan sonra bir ProgressBar öğesinin görev tamamlandığında yavaşça dolduğu öğelerin bir listesi olmalıdır. Örneğin, her birinin indir düğmesiyle dosyaların bir listesini yapın. İndirme düğmesine tıklandığında, dosya arka planda indirilir ve dosyanın ne kadar yakın olduğunu gösteren bir ilerleme çubuğu doldurulur.ListView/OnClick'e bir ProgressBar ekleme Tek bir saat olarak adlandırılan
Bunu yapmak için, zaman zaman yeniden biçimlendirmek üzere bağdaştırıcıda notifyDataSetChanged öğesini çağıran bir AsyncTask oluşturuyorum. Bu bir düğmeyi tıklatıldıktan sonra, AsyncTask tamamlanana kadar, ListView'deki diğer düğmeleri tıklayamıyorum. Birisi bana neyi yanlış yaptığımı söyler mi?
Bunu Ice Cream Sandwich üzerindeki emülatörde (x86) çalıştırıyorum.
: Sonra ListView DownloadItem listesini uyarlar bir ArrayAdapter sahipclass 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
}
:
Ben İndirme ilerlemesini (aşağıdaki kod kısalık için basitleştirilmiş) temsil edecek bir DownloadItem var
class DownloadArrayAdapter extends ArrayAdapter<DownloadItem> {
List<DownloadItem> mItems;
public DownloadArrayAdapter(List<DownloadItem> items) {
mItems = items;
}
@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");
}
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);
return row;
}
}
Şimdiye kadar çok iyi - bu, listeyi düzgün bir şekilde işler. Ben de sadece yürütme olarak executeOnExecutor ile bu çalıştı, ama hiç şansım ettik
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)
}
}
: Benim Aktivite, ben OnClickListener var. DownloadTask şudur:
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();
}
}
Bu çalışma - neredeyse. Bunu yaptığımda, bir düğmeyi tıklattıktan sonra, ProgressBar normal olarak güncelleştirir - ancak AsyncTask döndürene kadar ListView'deki diğer düğmeleri tıklayamıyorum. Diğer bir deyişle, onDownloadButtonClick hiçbir zaman aranmaz. MAdapter.notifyDataSetChanged() çağrısını onProgressUpdate işlevinden kaldırırsam, birden çok görev eşzamanlı olarak güncelleştirilir, ancak elbette, liste geçersiz sayılmaz ve bu nedenle değişiklikleri görmek için gezinmem gerekir.
Neyi yanlış yapıyorum ve bunu nasıl düzeltebilirim?
Düzenleme: Bunu biraz daha oynanır ve notifyDataSetChanged çağırarak sıklığı onClick çağrılan ya da sadece kaybolmasını olmadığını etkiler gibi görünüyor. Yukarıdaki kod ile, çılgınca tıklayarak, bazen başlatmak için ikinci bir indirme çubuğu alabilirsiniz. Thread.Sleep'ı 2000 gibi daha büyük bir şeye artırırsam, liste beklediğim gibi çalışır.
Yani yeni soru - denilmekten onClick engellemediğini iken nasıl güncellemek için ProgressBars sorunsuz alabilirim?
2.DÜZENLEME:
@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;
}
liste görünümünü kullanmak görünüyor? Eğer öyleyse, ve zamanınız varsa, bunu izlemeyi düşünüyorum: [Google I/O 2010 - Liste Görünümü] (http://www.youtube.com/watch?v=wDBM6wVEO70). Bir öneri: 'Thread.sleep (800)' kullanabilirsiniz (örneğin), '10' gerekli değildir. –
Tıklama dinleyicisini nerede belirlersiniz? Bunu kukla kodda özlüyorsun. – reTs
@reTS: XML için bu düğmeyi, android: onClick parametresiyle ayarlayın. İşleyici kesinlikle çağrılıyor - bir kere, bir kere. Bununla birlikte benim de sorguma bak. – mindvirus