108

を使用して、バックグラウンドスレッドでリモートオーディオファイルフェッチおよびオーディオファイル再生操作を実行していますAsyncTaskCancellableフェッチ操作が実行されている間、進行状況バーが表示されます。

AsyncTaskユーザーが操作をキャンセル(決定)したときに実行をキャンセル/中止したい。そのような場合を処理する理想的な方法は何ですか?

4

9 に答える 9

77

私がどこでも使用してきた が実際には何もしないことをAlertDialogs発見しました。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;
    }

    // ...

}
于 2010-04-29T19:28:29.503 に答える
76

あなたが計算をしているなら

  • isCancelled()定期的にチェックする必要があります。

HTTP リクエストを実行している場合:

  • HttpGetorのインスタンスをHttpPostどこかに保存します (例: public フィールド)。
  • を呼び出した後cancel、 を呼び出しますrequest.abort()。これにより、IOExceptionが内部にスローされますdoInBackground

私の場合、さまざまな AsyncTasks で使用するコネクタ クラスがありました。簡単にするために、abortAllRequestsそのクラスに新しいメソッドを追加し、 を呼び出した直後にこのメソッドを呼び出しcancelました。

于 2012-06-10T23:03:29.377 に答える
20

問題は、 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;
        }
     }
于 2011-07-05T19:34:21.440 に答える
11

シンプル:を使用しないでくださいAsyncTaskAsyncTaskすぐに終了する(数十秒)短い操作用に設計されているため、キャンセルする必要はありません。「オーディオファイルの再生」は対象外です。通常のオーディオファイルの再生には、バックグラウンドスレッドも必要ありません。

于 2010-04-29T13:19:45.280 に答える
4

これが私がAsyncTaskを書く方法です
。重要なポイントはaddThread.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;
    }
于 2011-06-02T09:10:25.640 に答える
4

これを行う唯一の方法は、isCancelled() メソッドの値を確認し、true が返されたときに再生を停止することです。

于 2010-05-03T19:34:41.373 に答える
0

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(). しかし、少なくとも非同期タスクの終了は保証されています。

于 2013-06-11T13:55:10.160 に答える
0

グローバル 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);
    }

わたしにはできる。

于 2013-02-11T10:21:16.200 に答える