Android - Отмените AsyncTask сильно

Я реализовал AsyncTask в своем действия:

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

Теперь, я должен реализовать функциональность кнопки "Cancel", таким образом, я должен остановить выполнение выполняющейся задачи. Я не знаю, как я останавливаю выполняющуюся задачу (фоновая задача).

Поэтому предложите меня, как я отменяю AsyncTask сильно?

Обновление:

Я нашел о Cancel() метод того же, но я нашел тот вызов cancel(boolean mayInterruptIfRunning) не обязательно останавливает выполнение фонового процесса. Все, что, кажется, происходит, - то, что AsyncTask выполнит onCancelled () и не выполнит onPostExecute (), когда он завершится.

62
задан 20 January 2011 в 18:32

6 ответов

Просто проверьте isCancelled() время от времени:

 protected Object doInBackground(Object... x) {
    while (/* condition */) {
      // work...
      if (isCancelled()) break;
    }
    return null;
 }
90
ответ дан 31 October 2019 в 13:26

Упомянутый в случае комментариев, который 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 был частным классом одного из представлений, таким образом, методы считывания или методы set флага были необходимы для информирования AsyncTask о в настоящее время фактическом флаговом значении.

Мои несколько тестов (AVD Android 4.2.2, Api 17) показали, что, если AsyncTask уже выполняет doInBackground, то isCancelled() не реагирует никоим образом (т.е. продолжает быть ложью) к любым попыткам отменить его, например, во время mViewGroup.removeAllViews(); или во время OnDestroy из эти MainActivity, каждый из которых приводит к отсоединению представлений

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

, Если мне удается вызвать остановку doInBackground() благодаря представленному FlagCancelled, затем onPostExecute(), назван, но ни onCancelled(), ни onCancelled(Void result) (начиная с уровня API 11) не вызываются. (Я понятия не имею, почему, вызовите, они должны быть вызваны, и onPostExecute() не должен, "Android документ API says:Calling отмена () метод гарантирует, что onPostExecute (Объект) никогда не вызывается". - IdleSun, ответ на подобный вопрос ).

, С другой стороны, если тот же AsyncTask не запустил doInBackground() перед отменой, то все в порядке, isCancelled() изменения в истинном и я могу проверить это в [1 127]

@Override
    protected void onCancelled() {
        Log.d(TAG, String.format("mAsyncTask - onCancelled: isCancelled = %b, FlagCancelled = %b", this.isCancelled(), FlagCancelled ));
    super.onCancelled();
}
5
ответ дан 31 October 2019 в 13:26

Даже при том, что AsyncTask не должен использоваться для длительных операций, иногда он может быть пойман в задаче, которая не отвечает (такие как не отвечающий HTTP-вызов). В этом случае может быть необходимо отменить AsyncTask.

Мы имеем к проблемам в выполнении этого. 1. Обычное диалоговое окно прогресса, отображенное с AsyncTask, является первой вещью, отмененной на AsyncTask, когда кнопка "Назад" нажимается пользователем. 2. AsyncTask может быть в doInBackground методе

Путем создания dismissDialogListerner на ProgressDialog, пользователь может нажать кнопку "Назад" и на самом деле аннулировать 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();
    }
}
2
ответ дан 31 October 2019 в 13:26

Наша глобальная переменная класса AsyncTask

LongOperation LongOperationOdeme = new LongOperation();

И действие KEYCODE_BACK, которые прерывают AsyncTask

   @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            LongOperationOdeme.cancel(true);
        }
        return super.onKeyDown(keyCode, event);
    }

, Это работает на меня.

1
ответ дан 31 October 2019 в 13:26

Звоните cancel() на AsyncTask. Отменит ли это на самом деле что-нибудь, зависит немного на то, что Вы делаете. Заключить Romain Guy в кавычки:

при вызове отмены (верной) прерывание будет отправлено в фоновый поток, который может помочь прерываемым задачам. Иначе необходимо просто удостовериться, что проверили isCancelled () регулярно в doInBackground () метод. Вы видите примеры этого по code.google.com/p/shelves.

49
ответ дан 31 October 2019 в 13:26

Это действительно зависит от того, что Вы делаете в своем asynctask.

, Если это - цикл, обрабатывающий много файлов, можно просто проверить после того, как каждый регистрирует, если isCanceled () флаг повышен или не, и затем повредитесь от цикла, если это.

, Если это - одна команда строки, которая выполняет очень длинную операцию, нет очень, можно сделать.

лучшее обходное решение не должно было бы использовать метод отмены asynctask и использовать Вашу собственную cancelFlag булевскую переменную. Можно затем протестировать этот cancelFlag в Вашем поствыполняющиеся для решения, что сделать с результатом.

16
ответ дан 31 October 2019 в 13:26

Другие вопросы по тегам:

Похожие вопросы: