Завершить AsyncTask по нажатию кнопки "назад"

Рейтинг: 0Ответов: 2Опубликовано: 01.12.2014

Добрый день. Помогите корректно прервать асинхронную задачу по нажатию "назад". В данный момент логика следующая в приложении.

  1. Из главной OnCreate вызывается наследованный от AsyncTask UpdateTask.
  2. В doInBackground создается экземпляр JSONParser и у него вызывается метод, создающий экземпляр DefaultHttpClient и запускающий его на выполнение (во время которого качается длинная json строка).

То есть асинхронная загрузка внутри асинхронной задачи. Вопрос:

  1. Как обнаружить нажатую кнопку "назад"?
  2. Как прервать загрузку?

Я понял, что если в doInBackground выполняется цикл, то при желании можно проверять на каждой итерации прервана ли задача, что-то вроде:

protected Void doInBackground(Void... params) {
  for (int i = 0; i < 5; i++) {
    TimeUnit.SECONDS.sleep(1);
    if (isCancelled()) {
      Log.d(LOG_TAG, "Cancelled");
      return null;
    }
  }
  return null;
}

...

//где-то в программе
if(*нажата клавиша "назад"*)
  mt.cancel(false)

Но как я вклинюсь в задачу загрузки данных? А то у меня на данный момент, если во время загрузки выйти из приложения (назад или home), то через какое-то время выходит сообщение об ошибке (загрузка продолжается в фоне и не корректно реагирует по окончанию).

Ответы

▲ 1Принят

Ок, можно поразмышлять:

1) Как я уже сказал, решение в лоб: в onPostExecute чекать контекст, если null, значит приложение закрыто/свёрнуто, тогда ничего не делаем. Независимо от того, что вы ещё сделаете, эта проверка в любом случае нужна.

2) Если у вас там HttpClient, то запрос можно отменить:

httpClient.getConnectionManager().shutdown();

Логика:

а) В AssyncTask объявить public метод для отмены запроса.

б) В Activity отлавливать нажатия. Если кнопка Back нажата, то вызывать public метод тот и закрывать соединение httpClient.getConnectionManager().shutdown()

▲ 1

AsyncTask.cancel() сам по себе ничего не отменяет - он просто выставляет флаг: cancel, не cancel. Дальше уже проблема разработчика правильно проверить этот флаг и правильно завершить задачу.

В данном случае, я бы написал отдельный синхронизированный метод завершения AsyncTask, в котором корректно закрывается сокет/коннект, парсер Json и проч. дела. То есть в общем примерно то что описал @Suvitruf, но только обрамленный synchronized