Android asynctask show progress dialog until function has finished - android

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

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.

ProgressDialog showing for a fraction of a second, if at all

I am working on a calculator app for my first project with android. Some of the calculations take a while because of how many operands are put in the equation. I'm using mxparser api to evaluate the equation. A progressDialog is supposed to show during my asyncTask, but it only shows for a fraction of a second if at all.
I have tried other solutions on stackoverflow and nothing so far has worked. Any ideas as to why this is occurring?
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private EditText editScreen;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
editScreen = (EditText) findViewById(R.id.calculator_display);
Button btnEq = (Button) findViewById(R.id.btn_equals);
btnEq.setOnClickListener(this);
}
#Override
public void onClick(View v) {
String equation = editScreen.getText().toString();
switch (v.getId()) {
case R.id.btn_equals:
doCalculation(equation);
break;
default:
Log.e("ERROR", "button was not implemented: " + v.getId());
}
}
private void doCalculation(String equation) {
Expression expression = new Expression(equation);
boolean isCorrectSyntax = expression.checkSyntax();
if (isCorrectSyntax) {
new calcAsync(MainActivity.this, equation).execute(expression);
} else {
Toast.makeText(getApplicationContext(), "Error in expression, please check syntax", Toast.LENGTH_LONG).show();
}
}
private class calcAsync extends AsyncTask<Expression, Void, Void> {
private ProgressDialog dialog;
private String equation;
private String answer;
public calcAsync(Context context, String equation) {
this.equation = equation;
}
#Override
protected Void doInBackground(Expression... params) {
Log.d("DEV", "starting calculation");
Double result = params[0].calculate();
String[] r = result.toString().split("\\.");
if (result.equals(Double.NaN) || result.equals(Double.NEGATIVE_INFINITY) || result.equals(Double.POSITIVE_INFINITY)) {
answer = result.toString();
} else if (r[1].length() == 1 && Integer.parseInt(r[1]) == 0) {
answer = r[0];
} else {
answer = result.toString();
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(MainActivity.this);
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.setMessage("Calculating...");
dialog.setTitle("Please wait...");
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.show();
Log.d("DEV", "dialog shown");
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (dialog != null) {
Log.d("DEV", String.valueOf(dialog.isShowing()));
dialog.dismiss();
Log.d("DEV", "Dialog dismissed");
}
editScreen.setText(answer);
saveToHistory(equation, answer);
}
}
}
Update 7/14/16:
It seems that the actual calculation itself doesn't take long at all. But from the time it takes after the equals button is pressed, until the result is displayed takes a while. 3 seconds for a long string of 1+1... (33 additions in my testing), longer if the string is longer than that.
Update 7/18/16:
I found out why my progressDialog wasn't showing. In the doCalculation method I am checking the syntax with equation.checkSyntax() before the asyncTask. This is where my delay was coming from, so the asyncTask wasn't doing the bulk of the work. after adding it in the asyncTask, I noticed that it takes considerably longer for the same test case as my previous update.
If you know that the delay occurs from the time the equals button is pressed, why not move the ProgressDialog to start there instead?

How do you clear a determinate progress bar for reuse?

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

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

Categories

Resources