回答:
ちょうどことを発見AlertDialogs
「S boolean cancel(...);
私はどこにでも実際に使用して何もしませんしてきました。すごい。
そう...
public class MyTask extends AsyncTask<Void, Void, Void> {
private volatile boolean running = true;
private final ProgressDialog progressDialog;
public MyTask(Context ctx) {
progressDialog = gimmeOne(ctx);
progressDialog.setCancelable(true);
progressDialog.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
// actually could set running = false; right here, but I'll
// stick to contract.
cancel(true);
}
});
}
@Override
protected void onPreExecute() {
progressDialog.show();
}
@Override
protected void onCancelled() {
running = false;
}
@Override
protected Void doInBackground(Void... params) {
while (running) {
// does the hard work
}
return null;
}
// ...
}
while(running)
とwhile(!isCancelled())
他の人がコメントの中で、ここで述べてきたように。
計算をしている場合:
isCancelled()
定期的にチェックする必要があります。HTTPリクエストを実行している場合:
HttpGet
またはHttpPost
どこかにインスタンスを保存します(例:パブリックフィールド)。cancel
、を呼び出しますrequest.abort()
。これはIOException
内にスローされますdoInBackground
。私の場合、さまざまなAsyncTaskで使用するコネクタクラスがありました。簡単にするために、abortAllRequests
そのクラスに新しいメソッドを追加し、を呼び出しcancel
た直後にこのメソッドを呼び出しました。
HttpGet.abort()
バックグラウンドスレッドから呼び出す必要があります。そうしないと、android.os.NetworkOnMainThreadException
。
cancel(true)
、リクエストを中断しないでください。ドキュメントから:If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.
HttpURLConnection.disconnect();
cancel(true)
。私はそれを使用し、それは動作します。
重要なのは、AsyncTask.cancel()呼び出しがタスクのonCancel関数のみを呼び出すことです。これは、キャンセル要求を処理する場所です。
これは、更新メソッドをトリガーするために使用する小さなタスクです
private class UpdateTask extends AsyncTask<Void, Void, Void> {
private boolean running = true;
@Override
protected void onCancelled() {
running = false;
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
onUpdate();
}
@Override
protected Void doInBackground(Void... params) {
while(running) {
publishProgress();
}
return null;
}
}
running
フラグを作成する必要はありません。AsyncTaskには、タスクがキャンセルされたときに設定される内部フラグがあります。交換してくださいwhile (running)
とwhile (!isCancelled())
。 developer.android.com/reference/android/os/… したがって、この単純なケースでは、onCancelled()
オーバーライドする必要はありません。
シンプル:を使用しないでくださいAsyncTask
。AsyncTask
は短時間で終了する(数十秒)ため、キャンセルする必要がない短い操作用に設計されています。「オーディオファイルの再生」は対象外です。通常のオーディオファイルの再生には、バックグラウンドスレッドは必要ありません。
onPostExecute()
て、作業を続行する必要があるかどうかを確認します。
これが、AsyncTask
の記述方法です。重要な点は、Thread.sleep(1)を追加することです。
@Override protected Integer doInBackground(String... params) {
Log.d(TAG, PRE + "url:" + params[0]);
Log.d(TAG, PRE + "file name:" + params[1]);
downloadPath = params[1];
int returnCode = SUCCESS;
FileOutputStream fos = null;
try {
URL url = new URL(params[0]);
File file = new File(params[1]);
fos = new FileOutputStream(file);
long startTime = System.currentTimeMillis();
URLConnection ucon = url.openConnection();
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
byte[] data = new byte[10240];
int nFinishSize = 0;
while( bis.read(data, 0, 10240) != -1){
fos.write(data, 0, 10240);
nFinishSize += 10240;
**Thread.sleep( 1 ); // this make cancel method work**
this.publishProgress(nFinishSize);
}
data = null;
Log.d(TAG, "download ready in"
+ ((System.currentTimeMillis() - startTime) / 1000)
+ " sec");
} catch (IOException e) {
Log.d(TAG, PRE + "Error: " + e);
returnCode = FAIL;
} catch (Exception e){
e.printStackTrace();
} finally{
try {
if(fos != null)
fos.close();
} catch (IOException e) {
Log.d(TAG, PRE + "Error: " + e);
e.printStackTrace();
}
}
return returnCode;
}
グローバルAsyncTaskクラス変数
LongOperation LongOperationOdeme = new LongOperation();
そして、AsyncTaskを中断するKEYCODE_BACKアクション
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
LongOperationOdeme.cancel(true);
}
return super.onKeyDown(keyCode, event);
}
わたしにはできる。
cancel(true)
ソケットやファイルストリームを閉じる、ローカルデータベースにデータを書き込むなど、リソースを解放する必要があるため、非同期タスクを不必要に強制的に中断したくありません。一方、次のような状況に直面しています。非同期タスクが時間の一部を終了するのを拒否します。たとえば、メインアクティビティが閉じられているときに、アクティビティのonPause()
メソッド内から非同期タスクの終了を要求する場合があります。したがって、単にを呼び出すだけでは問題ありませんrunning = false
。私は混合ソリューションにrunning = false
取り掛かる必要があります。両方ともを呼び出し、非同期タスクが完了するまで数ミリ秒待ってから、cancel(false)
またはのいずれかを呼び出しますcancel(true)
。
if (backgroundTask != null) {
backgroundTask.requestTermination();
try {
Thread.sleep((int)(0.5 * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
if (backgroundTask.getStatus() != AsyncTask.Status.FINISHED) {
backgroundTask.cancel(false);
}
backgroundTask = null;
}
副次的な結果として、doInBackground()
終了後にonCancelled()
メソッドが呼び出されることもあれば、が呼び出されることもありonPostExecute()
ます。しかし、少なくとも非同期タスクの終了は保証されています。
'10年4月29日のYanchenkoの回答を参照してください。'doInBackground 'の下のコードをAsyncTaskのすべての実行中に複数回実行する必要がある場合、' while(running) 'アプローチの使用は適切です。「doInBackground」の下のコードをAsyncTaskの実行ごとに1回だけ実行する必要がある場合、「doInBackground」の下のすべてのコードを「while(running)」ループでラップしても、バックグラウンドコード(バックグラウンドスレッド)の実行は停止しません。 'while(running)'条件は、whileループ内のすべてのコードが少なくとも1回実行されると評価されるため、AsyncTask自体はキャンセルされます。したがって、(a。)「doInBackground」の下のコードを複数の「while(running)」ブロックに分割するか、(b。)多数の「isCancelled」を実行する必要があります。https://developer.android.com/reference/android/os/AsyncTask.html。
したがって、オプション(a。)の場合、Yanchenkoの回答を次のように変更できます。
public class MyTask extends AsyncTask<Void, Void, Void> {
private volatile boolean running = true;
//...
@Override
protected void onCancelled() {
running = false;
}
@Override
protected Void doInBackground(Void... params) {
// does the hard work
while (running) {
// part 1 of the hard work
}
while (running) {
// part 2 of the hard work
}
// ...
while (running) {
// part x of the hard work
}
return null;
}
// ...
オプション(b。)の場合、「doInBackground」のコードは次のようになります。
public class MyTask extends AsyncTask<Void, Void, Void> {
//...
@Override
protected Void doInBackground(Void... params) {
// part 1 of the hard work
// ...
if (isCancelled()) {return null;}
// part 2 of the hard work
// ...
if (isCancelled()) {return null;}
// ...
// part x of the hard work
// ...
if (isCancelled()) {return null;}
}
// ...