How do I update the state of a ProgressBar on ever

2019-04-11 09:17发布

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?

2条回答
混吃等死
2楼-- · 2019-04-11 09:46

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);
}
查看更多
疯言疯语
3楼-- · 2019-04-11 09:55

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.

查看更多
登录 后发表回答