添加进度条到ListView /的OnClick称为单时间 [英] Adding a ProgressBar to a ListView/OnClick called a single time

查看:223
本文介绍了添加进度条到ListView /的OnClick称为单时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个想法是有项目的地方单击某个项目后,一个进度条会慢慢填补的任务完成的列表。例如,图像文件的列表,与通过每一个一个下载按钮。当点击下载按钮,该文件在后台下载和一个进度条充满展示了如何关闭该文件完成。

The idea is to have a list of items where after clicking an item, a ProgressBar will slowly fill as the task is completed. For example, picture a list of files, with a Download button by each one. When the download button is clicked, the file is downloaded in the background and a progress bar is filled showing how close the file is to completion.

要做到这一点,我创建的AsyncTask偶尔调用notifyDataSetChanged适配器上重新绘制它。尽管这个作品被点击一个按钮后,直到AsyncTask的完成,我无法点击在ListView其他按钮。有人能告诉我什么,我做错了什么?

To accomplish this, I create an AsyncTask which occasionally calls notifyDataSetChanged on the adaptor to redraw it. While this works after one button is clicked, until the AsyncTask is completed, I am unable to click other buttons in the ListView. Can someone please tell me what I am doing wrong?

我对冰淇淋三明治模拟器(86)运行此。

I am running this on the emulator (x86) on Ice Cream Sandwich.

我有一个DownloadItem重新present下载的(在code以下被简化为简洁起见)的进展情况:

I have a DownloadItem to represent the progress of a download (the code below is simplified for brevity):

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
}

我再有一个适应DownloadItem列表为ListView一个ArrayAdapter:

I then have an ArrayAdapter that adapts a list of DownloadItem for the ListView:

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;
    }
}

到目前为止,一切都很好 - 这个正确呈现列表。在我的活动,我有onClickListener:

So far, so good - this properly renders the list. In my Activity, I have the 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是:

I've tried this with executeOnExecutor as well as just execute, but with no luck. DownloadTask is:

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();
    }
}

该作品 - 差不多。当我做到这一点,点击一个按钮后,该进度更新,因为正常的 - 但我不能点击其他按钮在ListView直到AsyncTask的回报。也就是说,onDownloadButtonClick不会被调用。如果我从onProgressUpdate功能删除mAdapter.notifyDataSetChanged()调用,多任务同时进行更新,当然,该列表不会失效,所以我必须滚动看到周围的变化。

This works - almost. When I do this, after clicking one button, the ProgressBar updates as normal - but I can't click other buttons in the ListView until the AsyncTask returns. That is, onDownloadButtonClick is never called. If I remove the mAdapter.notifyDataSetChanged() call from the onProgressUpdate function, multiple tasks are updated simultaneously, but of course, the list isn't invalidated and so I have to scroll around to see changes.

我在做什么错了,我怎么能解决这个问题?

What am I doing wrong, and how can I fix this?

编辑:我打这个更多一些,而且似乎调用notifyDataSetChanged频率影响的onClick是否被调用或者只是被丢失。有了上面code,通过点击疯狂地我可以偶尔得到第二下载栏启动。如果我增加了Thread.Sleep的东西更大,像2000年,该列表的工作,因为我原先预期。

I played with this some more, and it seems that the frequency of calling notifyDataSetChanged affects whether onClick is being called or just being lost. With the above code, by clicking frantically I can occasionally get a second download bar to start. If I increase the Thread.Sleep to something much larger, like 2000, the list works as I originally expected.

所以,新问题 - 如何获得的ProgressBars更新顺畅,而不是被称之为阻塞的onClick

So new question - how do I get the ProgressBars to update smoothly while not blocking onClick from being called?

编辑#2:我已经推了一个示例项目,这个问题到我的GitHub的帐户:的https:// github上。 COM / mdkess / ProgressBarListView

EDIT #2: I have pushed a sample project with this problem to my GitHub account: https://github.com/mdkess/ProgressBarListView

推荐答案

我已经想通了这一点。

而不是调用notifyDataSetChanged(),我保存的引用,每一个进度在DownloadItem对象。然后,通过ListView中滚动时,当旧的对象是通过为convertView,我删除了从旧DownloadInfo的进度,并把它放在新的。

Instead of calling notifyDataSetChanged(), I stored a reference to each ProgressBar in the DownloadItem object. Then, when scrolling through the ListView, when old objects were passed as convertView, I removed the ProgressBar from the old DownloadInfo and put it on the new one.

因此​​,getView我的阵列适配器则成了:

Thus, getView for my array adapter then became:

 @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然后将设置进度的进度,如果不是空的,这和预期一样。

The download AsyncTask would then set the progress on the progressBar, if it was not null, and this worked as expected.

我上传的修正code到GitHub上,你可以在这里看到:<一href="https://github.com/mdkess/ProgressBarListView">https://github.com/mdkess/ProgressBarListView

I uploaded the corrected code to GitHub, you can see it here: https://github.com/mdkess/ProgressBarListView

这篇关于添加进度条到ListView /的OnClick称为单时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆