How do I update the state of a ProgressBar on every element of a GridView / ListView?

徘徊边缘 提交于 2019-12-06 07:36:56

问题


Currently I have a GridView, and every element should have a separate ProgressBar. The elements represent separate downloads, and I'd like to show the state of the downloads using these ProgressBars.

But how should I update them? My problem is, that according to the docs (and what I've heard on the Google IO videos), the only way to update elements in AdapterViews is to update the assigned adapter, and call .notifyDatasetChanged() after every update.

Of course this does actually work in this case too, but the updates are quite frequent (5-10 updates sec). And calling .notifyDatasetChanged in this frequency breaks any interaction with the GridView. E.g. the user tries to long-click on an item in the Grid, but the clicking event stops, because a .notifyDatasetChanged was called to update the progress of a download.

Is there any other way to do this? Should I ditch AdapterViews and use something else?


回答1:


For situations like yours with many frequent updates (many times a second), notifyDatasetChanged isn't the right way to go - You need to update the individual views directly.

Without seeing your code and the relationship between a file download and an entry in the GridView, it's hard to say exactly what calls you'll need, but:

-GridView has a "getChildAt" you can use to grab a view at a specific index.
-There's no point in updating the view if it's not even visible. If it's not between getFirstVisiblePosition() and getLastVisiblePosition(), ignore it, it'll get drawn with updated data whenever it gets redrawn.




回答2:


I have done this in one project. You can update the UI if you are using Asysctask without .notifyDatasetChanged(). E.g I have a downloading method in my Utils. class

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

            }
    }

And in my 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 ;
    }
}

I start downloading when user lick on list row

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


来源:https://stackoverflow.com/questions/8118433/how-do-i-update-the-state-of-a-progressbar-on-every-element-of-a-gridview-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!