android 동기 - 안드로이드-강제로 AsyncTask 취소





비동기 cancel (6)


AsyncTask는 장기 실행 작업에 사용해서는 안되지만 응답이없는 작업 (예 : 응답하지 않는 HTTP 호출)에서 catch 될 수 있습니다. 이 경우 AsyncTask를 취소해야 할 수 있습니다.

우리는이 일에 도전해야합니다. 1. AsyncTask와 함께 표시되는 일반적인 진행 대화 상자는 사용자가 뒤로 버튼을 눌렀을 때 AsyncTask에서 취소 된 첫 번째 것입니다. 2. AsyncTask가 doInBackground 메소드에있을 수 있습니다.

ProgressDialog에 dismissDialogListerner를 작성하여 사용자는 뒤로 버튼을 눌러 실제로 AsycnTask를 무효화하고 대화 상자를 닫을 수 있습니다.

다음은 그 예입니다.

public void openMainLobbyDoor(String username, String password){
    if(mOpenDoorAsyncTask == null){
        mOpenDoorAsyncTask = (OpenMainDoor) new OpenMainDoor(username, password, Posts.API_URL, 
                mContext, "Please wait while I unlock the front door for you!").execute(null, null, null);
    }
}

private class OpenMainDoor extends AsyncTask<Void, Void, Void>{

    //declare needed variables
    String username, password, url, loadingMessage;
    int userValidated;
    boolean canConfigure;
    Context context;
    ProgressDialog progressDialog;

    public OpenMainDoor(String username, String password, String url, 
                Context context, String loadingMessage){
        userValidated = 0;
        this.username = username;
        this.password = password;
        this.url = url;
        this.context = context;
        this.loadingMessage = loadingMessage;
    }

    /**
     * used to cancel dialog on configuration changes
     * @param canConfigure
     */
    public void canConfigureDialog(boolean canConfigure){
        this.canConfigure = canConfigure;
    }

    @Override
    protected void onPreExecute(){
        progressDialog = new ProgressDialog(this.context);
        progressDialog.setMessage(loadingMessage);
        progressDialog.setIndeterminate(true);
        progressDialog.setCancelable(true);
        progressDialog.setOnCancelListener(new OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                mOpenDoorAsyncTask.cancel(true);
            }
        });
        progressDialog.show();
        this.canConfigure = true;
    }

    @Override
    protected Void doInBackground(Void... params) {
        userValidated = Posts.authenticateNTLMUserLogin(username, password, url, context);
        while(userValidated == 0){
            if(isCancelled()){
                break;
            }
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void unused){
        //determine if this is still attached to window
        if(canConfigure)
            progressDialog.dismiss();

        if(userValidated == 1){
            saveLoginValues(username, password, true);
            Toast.makeText(context, R.string.main_login_pass, Toast.LENGTH_SHORT).show();
        }else{
            saveLoginValues(username, password, false);
            Toast.makeText(context, R.string.main_login_fail, Toast.LENGTH_SHORT).show();
        }
        nullifyAsyncTask();
    }

    @Override
    protected void onCancelled(){
        Toast.makeText(context, "Open door request cancelled!", Toast.LENGTH_SHORT).show();
        nullifyAsyncTask();
    }
}

내 활동에서 AsyncTask를 구현했습니다.

 performBackgroundTask asyncTask = new performBackgroundTask();
 asyncTask.execute();

이제 "취소"버튼 기능을 구현해야하므로 실행중인 작업의 실행을 중지해야합니다. 실행중인 작업 (백그라운드 작업)을 어떻게 중지 시킬지 모르겠습니다.

그래서 제발 제안 해주세요, AsyncTask를 강제로 취소하는 방법은 무엇입니까?

최신 정보:

같은 Cancel() 메서드는 Cancel() 에 대해 발견하지만 cancel(boolean mayInterruptIfRunning) 호출 cancel(boolean mayInterruptIfRunning) 반드시 백그라운드 프로세스의 실행을 중지하지 않는 것으로 나타났습니다. 일어나는 모든 일은 AsyncTask가 onCancelled ()를 실행하고 완료되면 onPostExecute ()를 실행하지 않는다는 것입니다.




AsyncTask 에서 cancel() 을 호출하십시오. 이것이 실제로 어떤 것을 취소할지 여부는 여러분이하는 일에 조금 의존적입니다. Romain Guy의 말을 인용하자면 :

취소 (true)를 호출하면 인터럽트가 백그라운드 스레드로 보내져 인터럽트 가능한 작업을 도울 수 있습니다. 그렇지 않으면 doInBackground () 메소드에서 isCancelled ()를 정기적으로 확인해야합니다. code.google.com/p/shelves에서 예를 확인할 수 있습니다.




우리의 글로벌 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);
    }

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




isCancelled() always returns false even i call asynctask.cancel(true); 주석 케이스에 언급 된 isCancelled() always returns false even i call asynctask.cancel(true); 내 응용 프로그램을 닫으면 특히 유해하지만 AsyncTask는 계속 작동합니다.

이를 해결하기 위해 Jacob Nordfalk 코드가 제안한 방법을 다음과 같이 수정했습니다.

protected Object doInBackground(Object... x) {
    while (/* condition */) {
      // work...
      if (isCancelled() || (FlagCancelled == true)) break;
    }
    return null;
 }

주 활동에 다음을 추가했습니다.

@Override
protected void onStop() {
    FlagCancelled = true;
    super.onStop();
}

AsyncTask는 뷰 중 하나의 private 클래스이므로 AsyncTask에 현재 실제 플래그 값을 알리려면 getter 또는 setter가 필요합니다.

여러 번의 테스트 (AVD Android 4.2.2, Api 17)에서는 AsyncTask가 doInBackground 이미 실행하고있는 경우 isCancelled() mViewGroup.removeAllViews(); 취소하려는 시도에 전혀 반응하지 않습니다 (즉, false가 mViewGroup.removeAllViews(); 또는 MainActivityOnDestroy 동안, 각각은보기의 분리로 이어진다.

   @Override 
   protected  void  onDetachedFromWindow() { 
    mAsyncTask.cancel(false); // and the same result with mAsyncTask.cancel(true);
    super.onDetachedFromWindow(); 
   } 

도입 된 FlagCancelled 덕분에 doInBackground() 를 강제 FlagCancelled 하면 onPostExecute() 가 호출되지만 onCancelled() 또는 onCancelled(Void result) (API 레벨 11 이후)는 호출되지 않습니다. (나는 왜 호출해야하고 onPostExecute() 호출해서는 안되는 지 알지 못합니다. "안드로이드 API 의사는 cancel () 메소드를 호출하면 onPostExecute (Object)가 호출되지 않는다는 것을 보증합니다."- IdleSun , 비슷한 질문에 답변 ) .

반면에, 같은 AsyncTask가 취소하기 전에 doInBackground() 를 시작하지 않았다면, 모든 것은 괜찮습니다. isCancelled() 는 true로 변경되고,

@Override
    protected void onCancelled() {
        Log.d(TAG, String.format("mAsyncTask - onCancelled: isCancelled = %b, FlagCancelled = %b", this.isCancelled(), FlagCancelled ));
    super.onCancelled();
}



그것은 정말로 asynctask에서 무엇을하고 있는지에 달려 있습니다.

많은 파일을 처리하는 루프 인 경우 isCanceled () 플래그가 발생했는지 여부를 확인한 다음 루프에서 벗어나면 각 파일을 검사 할 수 있습니다.

매우 긴 작업을 수행하는 한 줄 명령 인 경우 수행 할 수있는 작업이 많지 않습니다.

가장 좋은 해결 방법은 asynctask의 cancel 메소드를 사용하지 않고 자신의 cancelFlag 부울을 사용하는 것입니다. 그런 다음 postExecute에서이 cancelFlag를 테스트하여 결과로 수행 할 작업을 결정할 수 있습니다.




에뮬레이터 시작 시간을 줄이려면 에뮬레이터를 시작하기 전에 "부트 애니메이션 비활성화"를 확인해야합니다. Android 설명서를 참조하십시오 .

혹시라도 모를 경우, 앱을 실행 / 디버깅 할 때마다 에뮬레이터를 닫을 필요가 없습니다. 이미 열려있는 상태에서 실행 / 디버그를 클릭하면 APK 파일이 에뮬레이터에 업로드되어 거의 즉시 시작됩니다. 에뮬레이터는 처음 시작할 때만 귀찮게 오래 걸립니다.

다음은 Android 에뮬레이터의 속도를 높이는 몇 가지 팁입니다. Android 에뮬레이터의 속도를 최대 400 %까지 늘리는 방법 입니다.





android android-asynctask