简体   繁体   中英

AsyncTask in Android starts but does not process

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM