Reputation: 748
I know that there are many similar AsyncTask
questions already, but in my case something is very unusual or am I missing something !?
As the AsyncTask
is not allowed to run more than once. I call it with new B().execute();
so it should create a separated instance on each run !? Right?
The problem is after the B class is created and executed once, it wont work the second time the user calls the startBClass()
method (just opens the dialog, but the actual work is not happening).
I just Debugged the code and realize that after the Dialog is closed, the Thread is still running in the background. What is the proper way to stop the background thread when the Dialog is closing? - And since I'm closing the first Dialog inside B class and create another instance of the B class, why is the second one not working? Can't multiple AsyncTasks run in parallel !?
I simplified the classes for easier understanding what I'm trying:
public class A {
/* Is called when user clicks a button */
private void startBClass() {
new B().execute();
}
/* Opens a Dialog with a countdown TextView (works first call only) */
private class B extends AsyncTask<Void, Integer, Void> {
private int secondsPassed = 0;
private double totalToPay = 0;
private Dialog dialog;
private TextView tvCost;
private Button dialogBtn;
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new Dialog(ConfigurationActivity.this);
dialog.setCancelable(true);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.dialog);
dialog.setCanceledOnTouchOutside(false);
dialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
onPostExecute(null);
}
});
tvCost = (TextView) dialog.findViewById(R.id.textCounter);
dialogBtn = (Button) dialog.findViewById(R.id.button1);
dialogBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
dialog.cancel();
}
});
dialog.show();
}
@Override
protected Void doInBackground(Void... arg0) {
while(true){
publishProgress(secondsPassed++);
SystemClock.sleep(1000);
}
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
totalToPay = 12.00;
tvCost.setText(totalToPay + " USD");
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
final AlertDialog alert = new AlertDialog.Builder(ConfigurationActivity.this).create();
alert.setTitle("Information");
alert.setMessage("You should pay about " + totalToPay + " USD.");
alert.setButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface alertDialog, int which) {
alertDialog.dismiss();
}
});
alert.show();
}
}
}
Upvotes: 1
Views: 172
Reputation: 22342
dialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
onPostExecute(null);
}
});
This is no good. Per the docs:
Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.
To end it, I'd change both the code above, and the while loop in doInBackground()
.
protected Void doInBackground(Void... arg0) {
while(running){
publishProgress(secondsPassed++);
SystemClock.sleep(1000);
}
}
running
is a boolean you set to true
in onPreExecute()
. Set it to false
when you want to end it. Then your loop will exit and onPostExecute()
will be called correctly.
Side note: Where is secondsPassed
ever used?
Upvotes: 1