How do you clear a determinate progress bar for reuse? - android

I have an Activity with a button that starts a long running task. I perform the task using an AsyncTask and display a determinate ProgressBar that is updated as the task progresses. Everything works fine the first time the task is run, but on subsequent runs the dialog appears, but is already at 100% and 100/100. I'm overriding both onCreateDialog and onPrepareDialog in my Activity. I presumed that using setProgress(0) would reset the dialog, but this isn't working. I use showDialog in the AsyncTask's onPreExecute method and dismissDialog in the AsyncTask's onPostExecute. The only way I've been able to get the dialog to reset is by using removeDialog in onPostExecute, but I would rather not recreate the dialog as I'm going to be reusing several times. The relevant code is below. This is on API level 10.
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case PROGRESS_DIALOG:
progressDialog = new ProgressDialog(ProtoBufSerializationTestActivity.this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setCancelable(true);
progressDialog.setMax(100);
progressDialog.setMessage("Testing...");
return progressDialog;
default:
return null;
}
}
#Override
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
switch (id) {
case PROGRESS_DIALOG:
ProgressDialog tmp = (ProgressDialog)dialog;
tmp.setProgress(0);
tmp.setSecondaryProgress(0);
return;
default:
Log.e("test", "Unknown dialog requested");
}
}
private class SerializationTestTask extends AsyncTask<Void, Integer, Long> {
#Override
protected void onPreExecute() {
showDialog(PROGRESS_DIALOG);
}
#Override
protected Long doInBackground(Void... params) {
long accumulator = 0;
int totalSize = 0;
for (int i = 0; i < 10000; i++) {
final long start = System.nanoTime();
//code to be timed
final long end = System.nanoTime();
accumulator += end - start;
if (i % 100 == 0) {
publishProgress(i);
}
}
return accumulator;
}
#Override
protected void onPostExecute(Long aLong) {
dismissDialog(PROGRESS_DIALOG);
results.setText(String.format("Serialized Message 10000 times.\nAverage time to serialize %.3fms", (double) aLong / 1e10));
}
#Override
protected void onProgressUpdate(Integer... values) {
progressDialog.incrementProgressBy(1);
}
Edit After taking #Arhimed's suggestion I ended up with the following code. It is much simpler. I could have used DialogFragment, but I don't think it is necessary in this case.
private class SerializationTestTask extends AsyncTask<Void, Integer, Long> {
private ProgressDialog dialog;
#Override
protected void onPreExecute() {
dialog = ProgressDialog.show(ProtoBufSerializationTestActivity.this, "Serialization Test", "Testing...", false);
}
#Override
protected Long doInBackground(Void... params) {
long accumulator = 0;
int totalSize = 0;
for (int i = 0; i < 10000; i++) {
final long start = System.nanoTime();
//code to be timed
final long end = System.nanoTime();
accumulator += end - start;
if (i % 100 == 0) {
publishProgress(i);
}
}
return accumulator;
}
#Override
protected void onPostExecute(Long aLong) {
dialog.dismiss();
results.setText(String.format("Serialized Message 10000 times.\nAverage time to serialize %.3fms", (double) aLong / 1e10));
}
#Override
protected void onProgressUpdate(Integer... values) {
dialog.incrementProgressBy(1);
}
}

Actually Arhimed is right and you can't do it but you can force progress bar to come to its zero state with 'dirty' way.For me the client wanted progress bar to zero its value no matter what,in case if user leave that activity,but in my case the progress was still there,and only was reseting from start.I had custom progress drawable and setProgress did not help me at all.So what i did was to call this method before actually setting the REAL drawable setProgressDrawable(null) this is dirty way clearing,but it do what you want,and afterwards just call same method with your own progressdrawable so it feels like it has been refreshed.Thats it..no other way you can achieve this unfortunately.

It is impossible to use ProgressDialog in that way. Your AsyncTask should create a new instance each time.

Actually setProgress(0) refreshes the display only if the progress is started.
So, you can force the refresh by calling onStart before setProgress, like this :
#Override
protected void onPrepareDialog(int id, Dialog dialog) {
super.onPrepareDialog(id, dialog);
ProgressDialog progress = (ProgressDialog)dialog;
progress.onStart();
progress.setProgress(0);
}

Related

I'm making a renaming application in Android

Andorid
I want to show progressdialog while doing renaming task. The dialog should appear after clicking rename button. However, the progress dialog appears after renaming function(loop) is ended. Here's my code
public void onRenameClicked(View v){
ProgressTask task = new ProgressTask();
task.execute();
for(int i = 0; i < num_of_files; i++){
rename(file[i]);
}
}
and Here's innerclass to show dialog
class ProgressTask extends AsyncTask<Integer, Void, Void>{
ProgressDialog pd = new ProgressDialog(MainActivity.this);
#Override
protected Void doInBackground(Integer... i) {
for(int j = 0; j < item.size(); j++) {
pd.setProgress(j);
pd.setMessage((j) + "/" + item.size());
}
return null;
}
#Override
protected void onPreExecute() {
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setTitle("변경중");
pd.setMax(item.size());
pd.show();
}
}
You do realize that you are calling your async task, with no data.. therfore its finishing quickly. You should probably pass in the list of files into the AsyncTask via arguments and then process those calls accordingly for each file INSIDE the AsyncTask and update the progress of the AsyncTask as you finish renaming files.
You have to use
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
pd.setProgress(values[0]);
pd.setMessage((values[0]) + "/" + values[1]);
}
and
publishProgress(j, item.size());
in the doInBackground(). These modifications are required because the setProgress and setMessage must be executed in the UI thread not in the background one.

Android asynctask show progress dialog until function has finished

I know this answer has already been answered multiple times but I cannot get it to work properly. It's starts with activity A where a user needs to login via the function authenticate. When the user hits the button login I want the progressdialog to appear until the function authenticate has got a response. While success you go to another activity where you can navigate through the app.. Anyway sometimes when the internet is slow or if you're on mobile internet I still see activity A for a few seconds doing nothing while the auth function is going on. When it's done the system hops to activity B.
I tried using sleep thread thingy but that's not the point.. I want the progressdialog to appear when the user hits login and dissapear when the auth function has been finished.
With the help of AsyncTask I sometimes see the dialog for one flash of a second but not how it should be.. I also want to use asynctask for loading my listviews but the dialog isn't doing what it should.
Here my AsyncTask code
public class HeavyWorker extends AsyncTask<String, Context, Void> {
private ProgressDialog dialog;
public HeavyWorker() {
}
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(AuthenticationActivity.this);
dialog.setMessage("Gettting data");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
}
#Override
protected Void doInBackground(String... params) {
authenticate(username, password, autoLogin);
return null;
}
#Override
protected void onPostExecute(Void result) {
if (dialog != null && dialog.isShowing()) {
dialog.dismiss();
}
}
}
And where I call the asynctask
builder.setTitle(R.string.dialog_authenticate)
.setIcon(R.drawable.ic_launcher)
.setView(viewInflater)
.setPositiveButton(R.string.dialog_button_login,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
EditText ETusername = (EditText) viewInflater.findViewById(R.id.username);
EditText ETpassword = (EditText) viewInflater.findViewById(R.id.password);
CheckBox optionAutoLogin = (CheckBox) viewInflater
.findViewById(R.id.autoLogin);
checkAutoLogin = 0;
if (optionAutoLogin.isChecked()) checkAutoLogin = 1;
username = ETusername.getText().toString();
password = ETpassword.getText().toString();
new HeavyWorker().execute();
//authenticate(ETusername.getText().toString(), ETpassword.getText().toString(), checkAutoLogin);
}
})
Any help or advice is appreciated.
Are you finishing the activity A when authentication success? In that case, you could skip onPostExecute
The Documentation gives you quite a good example: You can post the Progress in the onProgressUpdate(...) And can update it from doInBackground via publishProgress(int i)
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) {
//DO YOUR PROGRESSBAR THINGS HERE
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}

Cancel an executing task

When I log in into my app, an async task starts executing and while that task is being executed and I logout of app, that task is still running and give me the results after sometime(though I have logged out). I want to ask, is there any way to cancel that task so that it doesn't give me results?
class AsyncClass extends AsyncTask<>{
#Override
protected String doInBackground(Void... params)
{
if(isCancelled())
{
Log.d("isCancelled", iscancelled());
}
//call the webservice
}
}
Now there is some other class from where I'm calling
if(asyncTaskObject!=null){
asyncTaskObject.cancel(true);
asyncTaskObject=null;
}
But Log statement inside iscancelled() is never called.
Yes you can cancel AsyncTask using cancel(boolean). You can create an instance of AsyncTask class and call,
if(task != null && task.equals(AsyncTask.Status.RUNNING))
task.cancel(true);
I had the same problem just a day ago :)
A mixture of the 3 other answers that works for me.
First declare your asyncTask on a field:
private MyTaskClass miTask;
On the onCreate/onResume if an activity:
miTask = new MyTaskClass();
Then you can execute it in any method.
miTask.execute();
And in the onPause/onStop:
miTask.cancel(true);
This will only work if in your doInBackground you check isCancelled(), an example that i made for a cursor access that was already close if the fragment was dismissed:
#Override
protected Void doInBackground(Void... params) {
cached = true;
int idIndex = currentCursor.getColumnIndex(Contacts._ID);
int displayNameIndex = currentCursor
.getColumnIndex(Contacts.DISPLAY_NAME);
while (currentCursor.moveToNext()) {
if (isCancelled()) {
break;
}
Hope that helps, regards.
Alex
Yes, it possible.
YourAsyncTask mTask;
if(mTask!=null) mTask.cancel();
Thanks
as per this link use Task.cancel(true);and isCancelled()
private class UpdateLibrary extends AsyncTask<Void, Integer, Boolean>{
private ProgressDialog dialog = new ProgressDialog(Library.this);
private int total = Library.instance.appState.getAvailableText().length;
private int count = 0;
//Used as handler to cancel task if back button is pressed
private AsyncTask<Void, Integer, Boolean> updateTask = null;
#Override
protected void onPreExecute(){
updateTask = this;
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setOnDismissListener(new OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
updateTask.cancel(true);
}
});
dialog.setMessage("Updating Library...");
dialog.setMax(total);
dialog.show();
}
#Override
protected Boolean doInBackground(Void... arg0) {
for (int i = 0; i < appState.getAvailableText().length;i++){
if(isCancelled()){
break;
}
//Do your updating stuff here
}
}
#Override
protected void onProgressUpdate(Integer... progress){
count += progress[0];
dialog.setProgress(count);
}
#Override
protected void onPostExecute(Boolean finished){
dialog.dismiss();
if (finished)
DialogHelper.showMessage(Str.TEXT_UPDATELIBRARY, Str.TEXT_UPDATECOMPLETED, Library.instance);
else {
//Do nothing......
}
}
}

Loading State or Async Task

I have an activity that loads an xml file, but when the app is invoked without reply in 1 or 2 seconds, I wonder if I can put some kind of loading not to appear that the app crashed, thanks.
The rule of thumb is, if you do anything, use AsyncTask, otherwise your application will eventually crash on long network delays or large files.
private class doSomethingTask extends AsyncTask<SomeData,Integer,SomeData[]> {
private ProgressDialog dialog;
protected SomeData[] doInBackground(SomeData... values) {
int count = values.length;
for( int i=0; i<count; i++) {
publishProgress(count,i+1);
// do something here
....
//
if( isCancelled() ) return null;
}
return values;
}
protected void onPreExecute()
{
// show progress bar or something
dialog = new ProgressDialog(context);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setMessage(context.getString(R.string.downloading));
dialog.show();
}
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
dialog.setMax(values[0]);
dialog.setProgress(values[1]);
}
protected void onPostExecute(SomeData[] result) {
// kill progress bar here
if( this.dialog.isShowing()) {
this.dialog.dismiss();
}
}
}

Android ProgressDialog while selecting and deselecting checkboxes using AsyncTask

I'm a newbie to Android and I'm having some problems with the AsyncTask class. I have a lot of (over 100) check boxes which I want to select or deselect with a "select all" check box.
Unfortunately this takes quite some time, noticeable for the user, so I want to use the ProgressDialog to show that the selecting is in progress.
Now I know that updates of the UI elements are supposed to be done in the UI thread so I have the selecting code in the onProgressUpdate method but the ProgressDialog doesn't show up not until the processing (select or deselecting all checkboxes) is finished...
How is this supposed to be done? Is there any workaround or any other solution? I also tried to go through all the check boxes in the doInBackground() method but I get lots of weird errors (I guess it's because of the UI).
This is my code:
customPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(final Preference preference, final Object object) {
new CbSelection().execute(preference);
return true;
}
});
private class CbSelection extends AsyncTask<Preference, Boolean, Void> {
private ProgressDialog Dialog = new ProgressDialog(Preferences.this);
#Override
protected void onPreExecute() {
Dialog.setMessage("Please wait...");
Dialog.setCanceledOnTouchOutside(true);
Dialog.setCancelable(true);
Dialog.show();
}
#Override
protected Void doInBackground(Preference... pref) {
PreferenceScreen screen = (PreferenceScreen)getPreferenceScreen().getRootAdapter().getItem(2);
Preference preference = pref[0];
if(preference.getKey().compareTo("select_all") == 0){
publishProgress(true);
}
return null;
}
#Override
protected void onProgressUpdate(Boolean... ok) {
if(ok[0]== true) {
PreferenceScreen screen = (PreferenceScreen)getPreferenceScreen().getRootAdapter().getItem(2);
for(int i = 0; i < screen.getPreferenceCount(); ++i) {
//Dialog.show();
/* select or deselect all checkboxes here... */
}
}
}
#Override
protected void onPostExecute(Void v) {
Dialog.cancel();
}
}
What if you create and show the dialog before executing the AsyncTask? That's the way it usually is used:
private ProgressDialog Dialog;
customPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(final Preference preference, final Object object) {
Dialog = new ProgressDialog(Preferences.this);
Dialog.setMessage("Please wait...");
Dialog.setCanceledOnTouchOutside(true);
Dialog.setCancelable(true);
Dialog.show();
new CbSelection().execute(preference);
return true;
}
});
private class CbSelection extends AsyncTask<Preference, Boolean, Void> {
#Override
protected Void doInBackground(Preference... pref) {
PreferenceScreen screen = (PreferenceScreen)getPreferenceScreen().getRootAdapter().getItem(2);
Preference preference = pref[0];
if(preference.getKey().compareTo("select_all") == 0){
publishProgress(true);
}
return null;
}
#Override
protected void onProgressUpdate(Boolean... ok) {
if(ok[0]== true) {
PreferenceScreen screen = (PreferenceScreen)getPreferenceScreen().getRootAdapter().getItem(2);
for(int i = 0; i < screen.getPreferenceCount(); ++i) {
/* select or deselect all checkboxes here... */
}
}
}
#Override
protected void onPostExecute(Void v) {
Dialog.dismiss();
}
}

Categories

Resources