1

すでに似たような質問がたくさんあることは知っていますAsyncTaskが、私の場合、何かが非常に珍しいのか、何かが足りないのでしょうか!?

AsyncTaskは複数回実行することは許可されていないためです。で呼び出すnew B().execute();ので、実行ごとに個別のインスタンスを作成する必要があります!?右?

問題は、Bクラスが作成されて一度実行された後、ユーザーが2回目にstartBClass()メソッドを呼び出したときに機能しないことです(ダイアログを開くだけですが、実際の作業は行われません)。

コードをデバッグしたところ、ダイアログを閉じた後もスレッドがバックグラウンドで実行されていることがわかりました。ダイアログが閉じているときにバックグラウンドスレッドを停止する適切な方法は何ですか?-そして、Bクラス内の最初のダイアログを閉じてBクラスの別のインスタンスを作成しているのに、なぜ2番目のインスタンスが機能しないのですか?複数の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();
       }
   }
}
4

1 に答える 1

1
dialog.setOnCancelListener(new OnCancelListener() {
    @Override
    public void onCancel(DialogInterface dialog) {
        onPostExecute(null);
    }
});

これは良くありません。ドキュメントによると

onPreExecute()、onPostExecute(Result)、doInBackground(Params ...)、onProgressUpdate(Progress ...)を手動で呼び出さないでください。

これを終了するには、上記のコードと。のwhileループの両方を変更しますdoInBackground()

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

runningで設定したブール値trueですonPreExecute()false終了したいときに設定します。その後、ループが終了し、onPostExecute()正しく呼び出されます。

補足:どこsecondsPassedで使用されていますか?

于 2013-02-28T02:47:12.383 に答える