Идеальный способ отменить выполнение AsyncTask

Я запускаю операции удаленного аудиофайла и воспроизведения аудиофайлов в фоновом потоке с использованием AsyncTask . На момент выполнения операции выборки отображается индикатор выполнения Cancellable .

Я хочу отменить / прервать выполнение AsyncTask когда пользователь отменяет (отменяет) операцию. Каков идеальный способ справиться с таким делом?

Просто обнаружил, что boolean cancel(...); 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; } // ... } 

Если вы выполняете вычисления :

  • Вы должны периодически проверять 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
Ключевым моментом является добавление 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(); 

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

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

Меня устраивает.

Мне не нравится принудительно прерывать мои задачи async с cancel(true) без необходимости, потому что у них могут быть освобождены ресурсы, такие как закрытие сокетов или потоков файлов, запись данных в локальную базу данных и т. Д. С другой стороны, я столкнулся с Ситуации, в которых асинхронная задача отказывается заканчивать часть времени, например, иногда, когда основное действие закрывается, и я запрашиваю задачу async для завершения изнутри метода onPause() . Поэтому дело не просто в вызове running = false . Мне нужно пойти на смешанное решение: оба вызова running = false , а затем задание async на несколько миллисекунд, чтобы закончить, а затем вызвать либо 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() метод onCancelled() , а иногда и onPostExecute() . Но, по крайней мере, прерывание асинхронной задачи гарантировано.

Intereting Posts
Android expandablelistview не может отображать последнюю группу при расширении Как остановить диспетчер местоположений? Проблема с разработкой GearVR после экспорта в виде Google Android Project В EditText всплывающее диалоговое окно при нажатии на определенное подмножество текста Как узнать имя оператора на Android Фильтр Intent для запуска и отправки активности Где находится папка Android SDK? Собиратель мусора Android приостанавливает работу других приложений во время работы? Любой способ проверить, является ли выполняемый процесс системным процессом в android Отправка сообщения в приложение с сервера с помощью GCM Python и Android Android, javamail и proguard Сколько усилий я поставил в своей безопасности для Android In App Billing? Android – проверка активности в манифесте во время выполнения Преобразование неизменяемого файла растрового изображения в изменчивое растровое изображение