Выполнить AsyncTask несколько раз

В моей работе я использую класс, который простирается от AsyncTask и параметр, являющийся экземпляром этой AsyncTask. Когда я вызываю mInstanceOfAT.execute("") все в порядке. Но приложение падает, когда я нажимаю кнопку обновления, которая вызывает снова AsyncTask (в случае, если сетевое задание не работает). В результате возникает исключение, в котором говорится:

Невозможно выполнить задачу: задача уже выполнена (задача может быть выполнена только один раз)

Я попытался вызвать cancel (true) для экземпляра Asyctask, но он тоже не работает. Единственное решение – создать новые экземпляры Asyntask. Правильно ли это?

Благодарю.

Solutions Collecting From Web of "Выполнить AsyncTask несколько раз"

AsyncTask могут использоваться только один раз.

Вместо этого просто вызовите свою задачу, как new MyAsyncTask().execute("");

Из документов API AsyncTask:

Правила потоковой передачи

Для правильного функционирования этого класса необходимо соблюдать несколько правил потоковой передачи:

  • Экземпляр задачи должен быть создан в потоке пользовательского интерфейса.
  • Execute (Params …) должен быть вызван в потоке пользовательского интерфейса.
  • Не вызывайте onPreExecute (), onPostExecute (Result), doInBackground (Params …), onProgressUpdate (Прогресс …) вручную.
  • Задача может быть выполнена только один раз (исключение будет выбрано при попытке выполнить второе выполнение).

Причины для экземпляров ASyncTask для Fire-and-forget подробно описаны в ответе Стива Прентиса. Однако, хотя вы ограничены тем, сколько раз вы выполняете ASyncTask, вы можете делать то, что вам нравится, пока поток работает. ,

Поместите исполняемый код внутри цикла в doInBackground () и используйте одновременную блокировку для запуска каждого выполнения. Вы можете получить результаты, используя publishProgress () / onProgressUpdate () .

Пример:

 class GetDataFromServerTask extends AsyncTask<Input, Result, Void> { private final ReentrantLock lock = new ReentrantLock(); private final Condition tryAgain = lock.newCondition(); private volatile boolean finished = false; @Override protected Void doInBackground(Input... params) { lock.lockInterruptibly(); do { // This is the bulk of our task, request the data, and put in "result" Result result = .... // Return it to the activity thread using publishProgress() publishProgress(result); // At the end, we acquire a lock that will delay // the next execution until runAgain() is called.. tryAgain.await(); } while(!finished); lock.unlock(); } @Override protected void onProgressUpdate(Result... result) { // Treat this like onPostExecute(), do something with result // This is an example... if (result != whatWeWant && userWantsToTryAgain()) { runAgain(); } } public void runAgain() { // Call this to request data from the server again tryAgain.signal(); } public void terminateTask() { // The task will only finish when we call this method finished = true; lock.unlock(); } @Override protected void onCancelled() { // Make sure we clean up if the task is killed terminateTask(); } } 

Конечно, это немного сложнее, чем традиционное использование ASyncTask, и вы отказываетесь от использования publishProgress () для фактической отчетности о ходе работы. Но если память беспокоит вас, тогда этот подход обеспечит сохранение только одной ASyncTask в куче во время выполнения.

Я поставил статические задачи вращения, которые затем помогли мне прикрепить, отсоединить и снова подключить их к потокам пользовательского интерфейса при изменениях вращения. Но чтобы вернуться к вашему вопросу, я создаю флаг, чтобы увидеть, работает ли поток. Когда вы хотите перезапустить поток, я проверяю, запущена ли задача вращения, если я хочу поджечь предупреждение. Если это не так, я делаю его нулевым, а затем создаю новый, который будет работать вокруг ошибки, которую вы видите. Кроме того, после успешного завершения я удаляю завершенную задачу, связанную с ротацией, так что она готова снова идти.

Я была такая же проблема. В моем случае у меня есть задача, которую я хочу сделать в onCreate() и в onResume( ). Поэтому я сделал статический Asynctask и получаю экземпляр из него. Теперь у нас все та же проблема.

Так что я сделал в onPostExecute ():

 instance = null; 

Помня, что я проверяю статический метод getInstance, что мой экземпляр не является нулевым, иначе я его создаю:

 if (instance == null){ instance = new Task(); } return instance; 

Метод postExecute очистит экземпляр и восстановит его. Конечно, это можно сделать вне класса.

Да, это правда, в документе говорится, что только одна из них может быть выполнена одной асинхронной.

Каждый раз, когда вам нужно его использовать, вы должны указать:

 // Any time if you need to call her final FirmwareDownload fDownload = new FirmwareDownload(); fDownload.execute("your parameter"); static class FirmwareDownload extends AsyncTask<String, String, String> { }