Pull to refresh

Comments 17

А я обычно реализую AsyncTask как внутренний класс для Activity и получаю доступ к компонентах Activity прямо из onPostExecute.
Тоже неплохой вариант. Но лично я бы его использовал только, когда AsyncTask выполнят какие-нибудь несложные операции.
Только сейчас понял насколько ваш способ красивее. Буду использовать. Спасибо: )
Хорошая, ёмкая и короткая статья. Спасибо вам. И добро пожаловать на Хабр!
Кстати, автор, а вы не задумывались, что будет, если активити разрушится до вызова onPostExecute?
Ну почему же, очень даже задумывался (и даже эксперементировал с этим). Но на самом деле проблемы никакой нет — вы всегда можете вызвать cancel вашего AsyncTask.
Ничего себе никакой — а memory leak за проблему уже не считается? :) Пока не завершится выполнение AsyncTask сборщик мусора не сможет собрать MyActivity.
Это бесспорно так, но как я сказал выше — просто вызовите Cancel вашего AsyncTask на onPause или onStop, ну или где вам будет угодно — и проблема решена.
В вызове AsyncTask.cancel никакой магии нет — задача завершится только если это возможно.
AsyncTask.cancel внутри вызывает FutureTask.cancel, который делает вот что:
Attempts to cancel execution of this task. This attempt will fail if the task has already completed, has already been cancelled, or could not be cancelled for some other reason.

Все зависит от того, что происходит в AsyncTask.doInBackground. Нужно удалять listener из AsyncTask, иначе можно получить memory leak.
Мне кажется, что получить memory leak, в данном случае, не так уж и просто, в самом худшем случае AsyncTask будет ждать таймаута, так что это даже нельзя назвать memory leak.
Не могли бы вы описать ситуацию в которой может возникнуть описанная вами проблема, и как бы вы ее решили на примере. Я был бы вам очень признателен, а то беседа принимает уж слишком абстрактный характер.
Вообще в конце концов вызов метода AsyncTask.cancel заканчивается вызовом Thread.interrupt, который в свою очередь просто выставляет флажок о том, что поток прерван.
Если поток в этот момент заблокирован на методах wait, sleep или join, то поток разблокируется и эти методы кинут InterruptedException. Если поток в этот момент занят чем-то другим и не заблокирован, то InterruptedException бросится сразу при первом вызове wait, sleep или join.

Такая проблема может возникнуть, если плохо написать метод AsyncTask.doInBackground :)
Т. е. так, чтобы он не предоставлял возможность отменить свое выполнение. Например, выполнять в нем какие-нибудь сложные расчеты, которые занимают много времени. При этом вызовов wait, sleep или join не будет. Если периодически не проверять не отменена ли задача и прекращать вычисления, то вызов AsyncTask.cancel ничего не даст.

В случае сетевого запроса скорее всего такой проблемы не возникнет, но лично я бы на всякий случай дополнительно в onStop убирал listener из AsyncTask.
Большое спасибо за пояснение. Вот теперь я с вами полностью согласен ;)
красивее все таки переопределить cancel с тем чтоб он сам чистил ссылку. либо воспользоваться слабыми ссылками. но лучше всего хорошо писать doInBackground
Ага, а еще лучше вообще сервис использовать для таких целей :)
Ну WeakReference тут лишнее, если уже собрались вызывать cancel. Так что да, можно просто в cancel занулять listener.
Делегат — это конечно хорошо. Но не тогда, когда этот делегат — Activity. Про memory leak уже сказали. Лучше пользоваться Handlers, это решает сразу проблему с утечкой, а так же обеспечивает низкую связность.
Sign up to leave a comment.

Articles