0

I am trying to use this library to publish progress on the Activity screen in the onProgressUpdate() of an AsyncTask, which is used to download some data from the internet. The demo application they have provided is using Handler to demonstrate this. I need to use it in an AsyncTask.

Following code snippet is from the code in their demo application.

My questions are:

  1. onProgressUpdate gets an argument Progress... values, and according to the documentation, it is "the values indicating progress." But I don't understand what this means, and how to I use this argument. In the examples I have seen, they are doing something like:

    progressBar.setProgress(Integer.parseInt(values[0]));
    

    Why are they using only the first value in the passed array (values[0])?

  2. How does the AsyncTask know how long is it going to take to finish the download operation. I want to show the ProgressBar progress from value 0 to 100 during the time spent to finish the download operation.

    By doing progressBarDeterminate.setVisibility(View.VISIBLE) in onPreExecute and doing progressBarDeterminate.setVisibility(View.GONE) in onPostExecute, we are ensuring that it only shows when the data is being downloaded, but how to we ensure that it progresses from starting position to final position during the time it takes to download the data (when we don't know precisely how long is it going to take to download the data) ?

CODE FROM DEMO EXAMPLE (It uses Handler, but I need to do this in AsyncTask)

public class MainActivity extends AppCompatActivity {
    ProgressBarDeterminate progressBarDeterminate;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        progressBarDeterminate = (ProgressBarDeterminate) findViewById(R.id.progressDeterminate);

        progressTimer.start();
    }


        Thread progressTimer = new Thread(new Runnable() {

                @Override
                public void run() {
                    for(int i = 0; i <= 100; i++){
                        try {
                            Thread.sleep(30);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        handler.sendMessage(new Message());
                    }
                }
            });

            Handler handler = new Handler(new Handler.Callback() {
                int progress = 0;
                @Override
                public boolean handleMessage(Message msg) {
                    progressBarDeterminate.setProgress(progress++);
                    return false;
                }
            });
}
Solace
  • 8,612
  • 22
  • 95
  • 183

1 Answers1

1

In answer to your first question, onProgressUpdate() takes a varargs argument. This means that it can take an indefinite number of arguments of the specified type. For example:

public void someMethod(String... args) {
    //...
}

Could be called either like this, someMethod("Hi!"), or this someMethod("Hi", "there", "welcome", "to", "SO").

More on varargs can be found here. These arguments are accessed in the same way as you would an array. If there is only one argument there, then you could use args[0].

Edit: In regards to your second question, as good an example as any is present in the Android Developers javadocs:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }

Namely, the answer really depends on your circumstances. Say in the above example that you need to download ten URLs. A for loop is set-up to download each URL sequentially, and once that URL has finished, publishProgress() is called, turning the current value into a percentage figure, (i / (float) count) * 100). Hopefully that answers your question!

PPartisan
  • 8,173
  • 4
  • 29
  • 48
  • 1
    As `doInBackground` takes a varargs argument, you can treat `urls` in the same way as you would an array (i.e. `URL[]` object). So, it has a length and `URL` members. – PPartisan Aug 20 '15 at 10:50
  • In my application, in `doInBackground`, the data is coming from a web service and it's type is complex (JSON-like) and then I parse it before returning it from `doInBackground`. So I have no idea how would I find out the number of iterations the for loop should iterate (i.e. the `count` variable). Can you suggest something? – Solace Aug 20 '15 at 10:51
  • I had posted the first comment before you edited the question, and after your edit, my question was answered. So I removed the comment. – Solace Aug 20 '15 at 10:52
  • 1
    @Solace Afraid not, sorry, I've never worked with `JSON` in Android. – PPartisan Aug 20 '15 at 10:53
  • 1
    No problem, and thank you so very much for your answer. I am going to accept it. I guess I am going to call `publishProgress` thrice, before making the call to the webservice, after the data has come and before it is parsed, after it is parsed. – Solace Aug 20 '15 at 10:55
  • 1
    @Solace That would work. Remember as well that if your situation doesn't lend itself well to a percentage-style update bar, you can return anything you like from `publishProgress()`, not just an `Integer`. It could be a `String` for a message, an image resource value etc. – PPartisan Aug 20 '15 at 11:09