Выполнение AsyncTask несколько раз
в моей деятельности я использую класс, который расширяет AsyncTask и параметр, который является экземпляром этого AsyncTask. Когда я звоню mInstanceOfAT.execute("") все нормально.
Но приложение падает, когда я нажимаю кнопку обновления, которая снова вызывает AsyncTask(в случае, если сетевое задание не работает). Причина тогда появляется исключение, которое говорит
Не удается выполнить задание: задача
уже выполнено (задача может быть
выполняется только один раз)
Я пробовал звонить отмена (true) для экземпляра Asyctask, но он также не работает. Единственное решение до сих пор это создать новые экземпляры Asyntask. Это правильный путь?
спасибо.
5 ответов:
AsyncTaskэкземпляры можно использовать только один раз.вместо этого просто назовите свою задачу как
new MyAsyncTask().execute("");из документов API AsyncTask:
правила резьбонарезной
есть несколько правил потоковой передачи, которые должны быть соблюдены для этого класса, чтобы работать должным образом:
- экземпляр задачи должен быть создан в UI-потоке.
- execute (Params...) должен быть вызван в UI-потоке.
- не вызывайте onPreExecute(), onPostExecute (результат), doInBackground(Params...), onProgressUpdate(прогресс...) вручную.
- задача может быть выполнена только один раз (исключение будет выдано при попытке второго выполнения.)
причины пожарных и забытых экземпляров ASyncTask довольно хорошо описаны в ответе Стива Прентиса - однако, пока вы ограничены во сколько раз вы выполняете 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 останется в куче во время выполнения.
Я сделал свои задачи вращения статическими, которые затем помогли мне прикрепить, отсоединить и снова прикрепить их к потокам пользовательского интерфейса при изменениях вращения. Но чтобы вернуться к вашему вопросу, я создаю флаг, чтобы увидеть, работает ли поток. Когда вы хотите перезапустить поток, я проверяю, запущена ли задача rotation, если это I toast a warning. Если это не так, я делаю его нулевым, а затем создаю новый, который будет работать вокруг ошибки, которую вы видите. Кроме того, после успешного завершения я обнуляю завершена ротация осознает задачу, так что он готов идти снова.
у меня была та же проблема. В моем случае у меня есть задача хочу сделать в
onCreate()иonResume(). Поэтому я сделал свой AsyncTask статическим и получил экземпляр из него. Теперь у нас все та же проблема.так что я сделал в onPostExecute () это:
instance = null;имея в виду, что я проверяю в статическом методе getInstance, что мой экземпляр не является нулевым, иначе я создаю его:
if (instance == null){ instance = new Task(); } return instance;метод в postExecute будет очистить экземпляр и воссоздать его. Из конечно, это может быть сделано вне класса.
Да это правда, док говорит, что может быть выполнена только одна Asyntask.
каждый раз, когда вам нужно использовать его надо так:
// 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> { }
Comments