Идея состоит в том, чтобы иметь список элементов, в котором после нажатия на элемент ProgressBar будет медленно заполняться по мере выполнения задачи. Например, представьте список файлов с кнопкой «Загрузить» для каждого из них. При нажатии кнопки загрузки файл загружается в фоновом режиме, и заполняется индикатор выполнения, показывающий, насколько файл близок к завершению.
Для этого я создаю AsyncTask, который время от времени вызывает notifyDataSetChanged на адаптере, чтобы перерисовать его. Хотя это работает после нажатия одной кнопки, до завершения AsyncTask я не могу нажимать другие кнопки в ListView. Может кто-нибудь, пожалуйста, скажите мне, что я делаю неправильно?
Я запускаю это на эмуляторе (x86 )на Ice Cream Sandwich.
У меня есть DownloadItem для представления хода загрузки (приведенный ниже код упрощен для краткости):
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, который адаптирует список DownloadItem для ListView :
class DownloadArrayAdapter extends ArrayAdapter {
List mItems;
public DownloadArrayAdapter(List 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;
}
}
. Пока все хорошо -, список корректно отображается. В моей деятельности у меня есть onClickListener:
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, а также просто выполнить, но безуспешно. DownloadTask:
class DownloadTask extends AsyncTask {
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
Это работает -почти. Когда я делаю это, после нажатия одной кнопки ProgressBar обновляется как обычно -, но я не могу нажимать другие кнопки в ListView, пока AsyncTask не вернется. То есть onDownloadButtonClick никогда не вызывается. Если я удаляю вызов mAdapter.notifyDataSetChanged ()из функции onProgressUpdate, несколько задач обновляются одновременно, но, конечно, список не становится недействительным, поэтому мне приходится прокручивать его, чтобы увидеть изменения.
Что я делаю не так, и как я могу это исправить?
Редактировать :Я еще немного поиграл с этим, и кажется, что частота вызова notifyDataSetChanged влияет на то, вызывается ли onClick или просто теряется. С приведенным выше кодом, отчаянно щелкая, я могу иногда запускать вторую полосу загрузки. Если я увеличу Thread.Sleep до чего-то гораздо большего, например 2000, список будет работать так, как я изначально ожидал.
Итак, новый вопрос -, как мне заставить ProgressBars плавно обновляться, не блокируя вызов onClick?
РЕДАКТИРОВАТЬ #2 :Я отправил пример проекта с этой проблемой в свою учетную запись GitHub:https://github.com/mdkess/ProgressBarListView