В моей работе я использую класс, который простирается от AsyncTask и параметр, являющийся экземпляром этой AsyncTask. Когда я вызываю mInstanceOfAT.execute("")
все в порядке. Но приложение падает, когда я нажимаю кнопку обновления, которая вызывает снова AsyncTask (в случае, если сетевое задание не работает). В результате возникает исключение, в котором говорится:
Невозможно выполнить задачу: задача уже выполнена (задача может быть выполнена только один раз)
Я попытался вызвать cancel (true) для экземпляра Asyctask, но он тоже не работает. Единственное решение – создать новые экземпляры Asyntask. Правильно ли это?
Благодарю.
AsyncTask
могут использоваться только один раз.
Вместо этого просто вызовите свою задачу, как new MyAsyncTask().execute("");
Из документов API AsyncTask:
Для правильного функционирования этого класса необходимо соблюдать несколько правил потоковой передачи:
Причины для экземпляров 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> { }