如何在GridView / ListView的每个元素上更新ProgressBar的状态?

时间:2011-11-14 07:20:26

标签: android android-ui android-gridview

目前我有一个GridView,每个元素都应该有一个单独的ProgressBar。元素代表单独的下载,我想使用这些ProgressBars显示下载的状态。

但是我应该如何更新它们呢?我的问题是,根据文档(以及我在Google IO视频中听到的内容),更新AdapterViews中元素的唯一方法是更新指定的适配器,并在每次更新后调用.notifyDatasetChanged()。

当然这在这种情况下确实有效,但更新非常频繁(5-10更新秒)。并且在此频率中调用.notifyDatasetChanged会破坏与GridView的任何交互。例如。用户尝试长按网格中的某个项目,但点击事件会停止,因为调用.notifyDatasetChanged来更新下载进度。

还有其他办法吗?我应该抛弃AdapterViews并使用其他东西吗?

2 个答案:

答案 0 :(得分:2)

对于像你这样频繁更新(多次一次)的情况,notifyDatasetChanged不是正确的方法 - 你需要直接更新各个视图。

如果没有看到您的代码以及文件下载与GridView中的条目之间的关系,很难确切地说出您需要的调用,但是:

-GridView有一个“getChildAt”,您可以使用它来获取特定索引的视图 - 如果视图甚至不可见,那么更新视图是没有意义的。如果它不在getFirstVisiblePosition()和getLastVisiblePosition()之间,则忽略它,只要重新绘制它就会得到更新的数据。

答案 1 :(得分:0)

我在一个项目中完成了这项工作。如果您使用不带.notifyDatasetChanged()的Asysctask,则可以更新UI。例如,我的Utils中有一个下载方法。类

public static String downloadFile(DownloadItem downItem, AsynBackGroundFileLoader asynBackGroundFileLoader, String fileName,
            String fileURL) {
                // Spiking my code 
            while (bufferLength = inputStream.read(buffer) > 0 ) {
                    fileOutput.write(buffer, 0, bufferLength);
                // add up the size so we know how much is downloaded
                downloadedSize += bufferLength;

                // this is where you would do something to report the progress,
                int pro = ((int) (downloadedSize * 100 / totalSize));

                asynBackGroundFileLoader.updateProgress(pro);

            }
    }

在我的AsyncTask中

public class AsynBackGroundFileLoader extends AsyncTask < Void , Integer , String > {



public AsynBackGroundFileLoader (DownloadItem dItem , TableLayout progressBarHodler , UpgradeActivity listener ) {
        try {
            mDownloadingProgressBarHolder = progressBarHodler ;
            this.mDownloadingProgressBarHolder.setVisibility ( View.VISIBLE ) ;

            mDownloadingProgressBar = ( ProgressBar ) mDownloadingProgressBarHolder.findViewById ( R.id.downloading_progress_bar ) ;
            downloadCancelButton = ( ImageButton ) mDownloadingProgressBarHolder.findViewById ( R.id.downloading_progress_cancel_btn ) ;
            downloadCancelButton.setImageResource ( R.drawable.btn_cancel );

    @ Override
    protected void onPreExecute ( ) {

    }

    @ Override
    protected String doInBackground ( Void ... params ) {

            boolean loadSuccess = Utils.downloadFile ( downItem , this , mFileName , downItem.getLink ( ) ) ;
        return ""+loadSuccess ;
    }

    @ Override
    protected void onPostExecute ( String result ) {

    }

    public void updateProgress ( int progressPercentage ) {
        try {
            if ( progressPercentage < 0 ) {
                progressPercentage = 0 ;
            } else if ( progressPercentage > 100 ) {
                progressPercentage = 100 ;
            }

//Here I am updating my UI without making list to notifyDataChanged()
                currentCompletedProgress = progressPercentage ;
                // This is my progressbar in UI that update , I got this progressbar by passing UI item view in constructor 
                mDownloadingProgressBar.setProgress ( progressPercentage ) ;
                downItem.setTotalProgress ( currentCompletedProgress ) ;
            } catch ( Exception e ) {
                Log.e ( TAG , "Exception = " + e.toString ( ) ) ;
                e.printStackTrace ( ) ;
            }

        }

    public ProgressBar getmDownloadinProgressBar ( ) {
        return mDownloadingProgressBar ;
    }
}

当用户舔列表行

时,我开始下载
public void onItemClick(AdapterView<?> tempadapter, View view, int position, long arg3) {
    TableLayout table = ((TableLayout) view.findViewById(R.id.downloading_progress_holder));
    DownloadItem temp = adapter.items.get(position);

        AsynBackGroundFileLoader bgdownloader = new AsynBackGroundFileLoader(temp, table, UpgradeActivity.this);
        bgdownloader.execute();
    }

    table.setVisibility(View.VISIBLE);
}