我知道已经有很多类似的AsyncTask问题,但是就我而言,这是非常不寻常的,还是我错过了某些事情!

因为AsyncTask不允许多次运行。我用new B().execute();称呼它,所以它应该在每次运行时创建一个单独的实例!对?

问题是在B类创建并执行一次之后,它在用户第二次调用startBClass()方法时将无法工作(只需打开对话框,但实际工作并未进行)。

我只是调试了代码,意识到关闭对话框之后,线程仍在后台运行。对话框关闭时停止后台线程的正确方法是什么? -而且由于我要关闭B类中的第一个Dialog并创建B类的另一个实例,所以为什么第二个不起作用?多个AsyncTasks不能并行运行吗?

我简化了类以更容易理解我在尝试什么:

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


不好根据the docs


  不要手动调用onPreExecute(),onPostExecute(Result),doInBackground(Params ...),onProgressUpdate(Progress ...)。


最后,我将更改上面的代码以及doInBackground()中的while循环。

   protected Void doInBackground(Void... arg0) {
       while(running){
           publishProgress(secondsPassed++);
           SystemClock.sleep(1000);
       }
   }


running是在true中设置为onPreExecute()的布尔值。要结束时将其设置为false。然后,您的循环将退出,并且onPostExecute()将被正确调用。

旁注:secondsPassed曾经在哪里使用?

10-07 19:35
查看更多