Wednesday, June 1, 2011

Doubling the AscyncTask Progress bar

Now that we've got the AsyncTask up and running - we've got to do it again! That's right, because, once we've downloaded the file, we need to extract it, and that take time, too. We'd like to show that progress instead of sitting with the old dialog box stuck on 100, leaving the customer in doubt as to what's going on (we've all been there on background activities).

We *could* run the extract in the same task as the download, but the problem with that is the old ProgressDialog refuses to disappear. Thus, we need to let that one finish, and then start up a second one to do the extract.

So, what does AsyncTask do to let the main UIThread know that it's done? Let's check out the docs.

http://developer.android.com/reference/android/os/AsyncTask.html

says that:

"onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter."

This is the ticket.

Let's test that with a toast:

@Override
protected void onPostExecute(String result) {
this.dialog.dismiss();
this.dialog = null;


Toast.makeText(getApplicationContext(), "onPostExecute", Toast.LENGTH_LONG)
.show();

//unzipFile();

}


Yes, the toast pops up. Well, we knew it would work because it had previously been executing the unzipFile. But it was quick and gives a visual starting point.

The next step is to create an AsyncTask out of the unZipFile. Here's the old one:

public class DownloadFilesTask extends AsyncTask {

private ProgressDialog dialog;
protected Context applicationContext;
int downloadFileSize = 0;
int numFilesInLevel = 0;

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

downloadFromUrl();

return "done";

}

@Override
protected void onPreExecute() {

this.dialog = new ProgressDialog(StartActivity.this);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setProgress(0);
dialog.setMessage("Loading...");
dialog.show();

}

// -- called from the publish progress
// -- notice that the datatype of the second param gets passed to this
// method
@Override
protected void onProgressUpdate(Integer... values) {

dialog.setProgress(values[0]);
}

// -- called if the cancel button is pressed
@Override
protected void onCancelled() {
}

// -- called as soon as doInBackground method completes
// -- notice that the third param gets passed to this method

@Override
protected void onPostExecute(String result) {
this.dialog.dismiss();
this.dialog = null;


Toast.makeText(getApplicationContext(), "onPostExecute", Toast.LENGTH_LONG)
.show();

//unzipFile();

}

Ok, so how to we change this? Change the name of the task, of course. Change the doInBackground to execute the unzipFile routine. And change the progress update to reflect the number of individual file to be extracted. And voila! Here's the functional code:



public class ExtractFilesTask extends AsyncTask {

private ProgressDialog dialog;
protected Context applicationContext;


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

unzipFile();
return "done";

}

@Override
protected void onPreExecute() {

this.dialog = new ProgressDialog(StartActivity.this);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setProgress(0);
dialog.setMessage("Extracting...");
dialog.show();

}

// -- called from the publish progress
// -- notice that the datatype of the second param gets passed to this
// method
@Override
protected void onProgressUpdate(Integer... values) {

dialog.setProgress(values[0]);
}

// -- called if the cancel button is pressed
@Override
protected void onCancelled() {
}

// -- called as soon as doInBackground method completes
// -- notice that the third param gets passed to this method

@Override
protected void onPostExecute(String result) {
this.dialog.dismiss();
this.dialog = null;

}


private void unzipFile() {...}

}

And now we've got both dialogues showing. Sweet.

No comments:

Post a Comment