실행중인 AsyncTask를 취소하는 이상적인 방법 표시 줄은 동작의

.NET을 사용하여 백그라운드 스레드에서 원격 오디오 파일 가져 오기 및 오디오 파일 재생 작업을 실행하고 AsyncTask있습니다. Cancellable진행 표시 줄은 동작의 실행을 인출 시간이 표시됩니다.

AsyncTask사용자가 작업을 취소 (반대 결정)하면 실행 을 취소 / 중단하고 싶습니다 . 그러한 사건을 처리하는 이상적인 방법은 무엇입니까?



답변

그냥 발견 AlertDialogsboolean 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;
    }

    // ...

}


답변

계산을하는 경우 :

  • isCancelled()주기적으로 확인 해야합니다.

HTTP 요청을하는 경우 :

  • 자신 HttpGet또는 HttpPost다른 곳에 (예 : 공개 필드) 인스턴스를 저장합니다 .
  • 호출 한 후 cancel, 호출 request.abort(). 이것은 IOException당신의 doInBackground.

제 경우에는 다양한 AsyncTasks에서 사용한 커넥터 클래스가있었습니다. 간단하게 abortAllRequests하기 위해 해당 클래스에 새 메서드를 추가 하고을 호출 한 직후이 메서드를 호출했습니다 cancel.


답변

문제는 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;
        }
     }


답변

간단합니다 AsyncTask.. AsyncTask빠르게 (수십 초) 종료되는 짧은 작업을 위해 설계되었으므로 취소 할 필요가 없습니다. “오디오 파일 재생”은 적합하지 않습니다. 일반 오디오 파일 재생을위한 백그라운드 스레드도 필요하지 않습니다.


답변

이를 수행하는 유일한 방법은 isCancelled () 메서드의 값을 확인하고 true를 반환하면 재생을 중지하는 것입니다.


답변

이것이 제가 AsyncTask를 작성하는 방법입니다
. 핵심은 add 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);
    }

그것은 나를 위해 작동합니다.