Урок 90. AsyncTask. Status – статусы задачи
Добавлено: 24 июн 2012, 23:00
В этом уроке:
- читаем статусы задачи
Click here to read this article!
- читаем статусы задачи
Click here to read this article!
Добро пожаловать на форум сайта
http://forum.startandroid.ru/
Код: Выделить всё
public class ThreeActivity extends Activity implements OnClickListener{
...
@Override
public void onClick(View v) {
....
}
}
Буду кратокbrucemax писал(а):Извините, что не по теме.. но у меня такая забавность) У меня на домашнем компе эклипс настоятельно требует убрать @Override в коде:
Спасибо, но краткость себя не оправдала=) Даже 1.7 пробывал.. таже проблема=)AndreyI писал(а):Буду кратокbrucemax писал(а):Извините, что не по теме.. но у меня такая забавность) У меня на домашнем компе эклипс настоятельно требует убрать @Override в коде:
Project->Properties, там находим Java Compiler и ставим Compiler compliance level 1.6 или выше
Так эта проблема популярна.. viewtopic.php?f=3&t=117&p=149#p150 всё списываем на версии javaAndreyI писал(а):Ну тогда просто удалите метод, эклипс начнет ругаться на не переопределенные методы интерфейса, пересоздайте метод автоматом (add unimplemented methods), только уровень компилятора должен быть 1.6 или выше (если будет ниже, то метод будет создан без @Override).
Еще попробуйте "Android Tools" -> "Fix Project Properties"
Т.е., после вызова TestTask.execute(); мы попадаем в doInBackground(), где входим в тело метода printText();, в котором, проверив выполнимость условий, инициируем onProgressUpdate(), затем отправляем сообщение на запуск atWorker, выходим из printText();, опять инициируем onProgressUpdate() и затем попадаем в onPostExecute(), после отработки которого, наша задача имеет статус FINISHED.EvilAngel писал(а):
- Почему при запуске задачи на экран сразу же выводится моё Toast-сообщение из onPostExecuted() ("AsyncTask has been stopped by setting CancelFlag"), тогда как AsyncTask работу свою ещё не завершил (о чём говорит циклически выполняющийся Log.d("MY_TEST_MESSAGE","atWorker still is working!");)?
- Почему нет никакой реакции на вызов метода MyTask.cancel(false) и т.о. всё, что в onCancelled() не обрабатывается?
Если честно, мне не совсем понятна логика... но сразу, что бросается в глаза - publishProgress()(в документации написано - protected final void publishProgress (Progress... values)), т.е. нужно передать int в метод... Это конечно может быть причиной, но почему то мне кажется, что если посмотреть log, многое станет понятно...EvilAngel писал(а):Добрый день!
Надеюсь тема ещё жива.
Не мог определиться, в ветку форума для какого урока поместить мой вопрос, потому продублировал его и в ветке 89 урока.
Хотел проверить работу AsyncTask совместно с Handler и Runnable и вошел в стопор. Суть моих двух проблем в ниже представленном коде такова:Буду благодарен любым ответам.
- Почему при запуске задачи на экран сразу же выводится моё Toast-сообщение из onPostExecuted() ("AsyncTask has been stopped by setting CancelFlag"), тогда как AsyncTask работу свою ещё не завершил (о чём говорит циклически выполняющийся Log.d("MY_TEST_MESSAGE","atWorker still is working!");)?
- Почему нет никакой реакции на вызов метода MyTask.cancel(false) и т.о. всё, что в onCancelled() не обрабатывается?
EvilAngel писал(а):Посредством дебагинга я в принципе ответил на оба своих вопроса.Т.е., после вызова TestTask.execute(); мы попадаем в doInBackground(), где входим в тело метода printText();, в котором, проверив выполнимость условий, инициируем onProgressUpdate(), затем отправляем сообщение на запуск atWorker, выходим из printText();, опять инициируем onProgressUpdate() и затем попадаем в onPostExecute(), после отработки которого, наша задача имеет статус FINISHED.EvilAngel писал(а):
- Почему при запуске задачи на экран сразу же выводится моё Toast-сообщение из onPostExecuted() ("AsyncTask has been stopped by setting CancelFlag"), тогда как AsyncTask работу свою ещё не завершил (о чём говорит циклически выполняющийся Log.d("MY_TEST_MESSAGE","atWorker still is working!");)?
- Почему нет никакой реакции на вызов метода MyTask.cancel(false) и т.о. всё, что в onCancelled() не обрабатывается?
Однако, теперь не ясно где выполняется запущенное повторяющееся событие?
И, можно ли не беспокоиться об какой-либо утечке (не только в данном случае, но и для любого другого повторяющегося кода), когда стопирующий флаг CancelFlag принимает значение true для обрыва процесса повторения?
И со вторым вопросом остаётся неясность, почему на Android 2.3.3 ввиду немедленного завершения doInBackground() метод TextTask.cancel(false), как теперь понятно ожидаемо, возвращает false, а, например, на Android 4.2 хотя метод TextTask.cancel(false) и возвращает false и в onCancelled() мы не попадаем, но задача может быть остановлена не только через флаг CancelFlag, но и этим методом?
Насчет publishProgress():altwin писал(а): Если честно, мне не совсем понятна логика... но сразу, что бросается в глаза - publishProgress()(в документации написано - protected final void publishProgress (Progress... values)), т.е. нужно передать int в метод... Это конечно может быть причиной, но почему то мне кажется, что если посмотреть log, многое станет понятно...
что никак НЕ ограничивает тип данных прогресса выполнения задачи только типом int.Progress, the type of the progress units published during the background computation.
В метод cancel() я передаю false, руководствуясь вполне резонным замечанием автора статьи. Во втором моём комментарии я попытался, пошагово следуя своим изысканиям, ответить на свой же вопрос "почему?"altwin писал(а): А по поводу второго вопроса я вообще завис... onCancelled() вызывается после отработки cancel() при условии, что возвращается значение true(опять же из доков), судя по тому, что пишете вы - насильно передаете false? т.е. таск завершается нормально и соответсвенно onCancelled() не вызывается вообще.
Собственно задачей я поставил перед собой исследовать такое взаимодействие трёх составляющих AsyncTask-Handler-Runnable, чтобы не прибегать к помощи циклов for или while, когда длительные повторяющиеся действия выносятся в отдельный поток.altwin писал(а): P.S. если честно я вообще не понимаю вашего кода, потому может пишу что -то не так. Но то, что сделал бы я - в корне изменил логику... тут есть уроки показывающие, как решается ваша задача.
onProgressUpdate() - третий метод с конца моего листинга (о publishProgress() я отписался выше).altwin писал(а):не дочитал - но сразу вопрос - onProgressUpdate() , я не увидел в вашем коде такого метода.... ваш метод printText вызывает publishProgress() при чем не передавая параметры..
просто в первом абзаце моего второго комментария, пошагово пробегая строки кода, я изложил свой ответ себе на "почему?"altwin писал(а):если честно после второго комментария я вас еще хуже понимать стал))
Runnable также присутствует в листинге и является частью моего класса MyAsyncTask:[syntax=java5]private class MyAsyncTask extends AsyncTask<Void,Void,Void>{altwin писал(а):Точно так же не понял где Runnable, который вы хотели попробовать и вообще что вы делаете... для начала думаю стоит описать цель,поскольку метод, которым вы идете явно не много не туда вас повел. Но вообще ответ прост onPostExecute вызывается после doInBackground, который завершил работу(а он ее завершил, но явно не так, как вы ожидали)).. нужно смотреть логи - уверен, там есть ответ.
не стоит полагаться на то, что ваш метод дождется окончания выполнения потока -по этому поводу четко сказано в документации java, поток не имеет четкого времени выполнения, в отличии от приведенного вами цикла. если хотите дождаться выполнения операции, то нужно выполнять синхронизацию, лучше для безопастности потоков лочить данные, вариантов много. То, что где то у вас получилось выполнить - говорит только о том, что приложение простое и запускали вы его не часто, когда основной код выполняется в main потоке, в котором вы запускаете второй, никто не гарантирует, что вы дождетесь завершения(нужна явная синхронизация), для примера можете просто сделать sleep() в doInBackground на несколько секунд и тогда скорее всего получите то, что хотите(методу придется дождаться), но это не решение. Лучше всего реализовать interface Lock на данных которые используются в потоке, и не выполнять к примеру publishProgress() до тех пор, пока данные из printText() не станут доступны. Таким образом doInBackground завершится только после получения... Не уверен, что правильно все сказал.. поскольку мне вообще трудно делать выводы о коде в котором столько Void классов... мне вообще не ясно зачем это делать, но думаю суть понятна. Либо синхронизировать, либо, что более потоко - безопастно ставить Lock.EvilAngel писал(а):Чтобы избавить Вас от изучения кода и попытки понять, что я имел ввиду, попытаюсь сконцентрировать внимание на том, что мне не ясно в данный конкретный момент:
Учитывая, что в методе doInBackground() я вызываю дополнительный метод printText(), в котором инициирую запуск Runnable, вызывающего этот же метод printText() и завершающегося при условии установки флага CancelFlag=true, получается, что doInBackground() не будет ждать когда завершится Runnable, и практически сразу получит управление из printText(), благополучно завершив свою работу и передав управление в onPostExecute(). А это значит, что задача получит статус ЗАВЕРШЕНА. При этом где-то в памяти будет продолжаться работа моего Runnable. Потому я и задал вопросы: где теперь выполняется запущенное повторяющееся событие и насколько потенциальна утечка памяти?
И, наконец, последнее. Т.к. doInBackground() не ожидает завершения запущенного Runnable, как это было бы, например, с while(...){...} (если, конечно, я правильно оценил свои наблюдения), то я ожидал, что TestTask.cancel(false) вернёт false и onCancelled() не будет достигнут. Так оно и произошло за исключением непонятного мне момента: на Android 2.3.3 TestTask.cancel(false) ни к чему не привел, тогда как на Android 4.2 хотя метод TextTask.cancel(false) и возвращает false и в onCancelled() мы не попадаем, но запущенный Runnable благополучно остановился.