Обработчик против AsyncTask

128

Я не понимаю, когда можно выбрать AsyncTask вместо Handler. Скажем, у меня есть код, который я хочу запускать каждые n секунд, чтобы обновлять пользовательский интерфейс. Почему я должен предпочесть одно другому?

Стив
источник
1
С AsyncTaskLoaders это стало более сложным. См. Stackoverflow.com/q/7120813/969325 для получения дополнительной информации.
Warpzit

Ответы:

75

IMO, AsyncTask был написан, чтобы обеспечить удобный и простой в использовании способ достижения фоновой обработки в приложениях Android, не беспокоясь о деталях низкого уровня (потоки, циклы сообщений и т. Д.). Он предоставляет методы обратного вызова, которые помогают планировать задачи, а также легко обновлять пользовательский интерфейс при необходимости.

Однако важно отметить, что при использовании AsyncTask разработчик подчиняется его ограничениям, которые возникают из-за проектных решений, принятых автором класса. Например, я недавно узнал, что существует ограничение на количество заданий, которые можно запланировать с помощью AsyncTasks.

Handler более прозрачен из двух и, вероятно, дает вам больше свободы; поэтому, если вам нужен больший контроль над вещами, вы должны выбрать Handler, иначе AsynTask будет работать нормально.

Samuh
источник
Это правильно. Я использовал AsyncTasks для всех фоновых операций в моем проекте. В какой-то момент я начал достигать этого максимального количества заданий, поэтому мои задачи начинались только после завершения другой. В конце концов, мне пришлось изменить всю свою структуру, чтобы перестать использовать асинтаксические задачи и избежать этого ограничения.
tbraun
5
Начиная с Honeycomb, AsyncTasksони выполняются в одном потоке, поэтому параллелизма больше нет. Вы по-прежнему можете запускать их в параллельной Executorреализации.
MrSnowflake
63

Мое практическое правило:

  • Если вы делаете что-то изолированное, связанное с пользовательским интерфейсом, например загружаете данные для представления в списке, продолжайте и используйте AsyncTask.

  • Если вы выполняете несколько повторяющихся задач, например загружаете несколько изображений, которые должны отображаться ImageViews(например, загружать эскизы) при загрузке, используйте очередь задач с Handler.

alexanderblom
источник
Обработчик находится на уровне API 1, а ASYNCTASK - на уровне API 3. Будет ли он устарел любой ценой? потому что я концентрируюсь на портировании приложений со старых версий на 2.2 и 2.3 ..
yokks
10
Ни то, ни другое не будет в ближайшее время прекращено. Обработчик никогда не будет устаревшим, поскольку пользовательский интерфейс в основном построен на нем.
alexanderblom
Разве вам не следует использовать загрузчик для загрузки данных для представления вашего пользовательского интерфейса?
nbarraille
19

Всегда старайтесь избегать использования AsyncTask, когда это возможно, в основном по следующим причинам:

  • AsyncTask не гарантированно запускается, так как существует база ThreadPool и максимальный размер, установленный системой, и если вы создадите слишком много asynctask, они в конечном итоге будут уничтожены

  • AsyncTask может быть автоматически завершен, даже во время работы, в зависимости от жизненного цикла активности, и вы не можете его контролировать.

  • Методы AsyncTask, работающие в потоке пользовательского интерфейса, такие как onPostExecute, могут выполняться, когда действие, на которое оно ссылается, больше не отображается или, возможно, находится в другом состоянии макета, например, после изменения ориентации.

В заключение вы не должны использовать связанные с UIThread методы AsyncTask, что является его основным преимуществом !!! Более того, над doInBackground следует выполнять некритическую работу. Прочтите эту ветку, чтобы узнать больше об этих проблемах:

Действительно ли AsyncTask концептуально ошибочен или я просто что-то упускаю?

В заключение попробуйте предпочесть использование IntentServices, HandlerThread или ThreadPoolExecutor вместо AsyncTask, когда любая из вышеперечисленных проблем может вас беспокоить. Конечно, это потребует дополнительной работы, но ваше приложение будет безопаснее.

типа a1pha
источник
Да, я потратил много времени, сожалея о многих случаях использования AsyncTasks. Они кажутся великолепными, но ... столько проблем!
SMBiggs
6
Мне очень жаль, что я так категорически опровергал ваши точки зрения, но я не могу допустить, чтобы ваш плохой стиль влиял на Android. Пункт первый. У вас НЕ должно быть запущено столько потоков. Если вы сталкиваетесь с этим, ваша архитектура - foobar. Пункт 2. Как, черт возьми ... Хорошо, да, все в Android - бесплатная игра для сборщика мусора ... Вы увидите только грубое поведение, как описано выше, в некоторых случаях, строго нарушающих задачу. Пункт 3. Управлять своей задачей, если не грубо, - навык новичка. Вы либо убиваете его, когда вызываете onPause, либо соответствующим образом отключаете и присоединяете.
StarWind0
1
vogella.com/tutorials/AndroidBackgroundProcessing/article.html Это все, что вам нужно, чтобы научиться правильно выполнять задачи без проблем, описанных выше (при условии, что вы не делаете что-то вроде того, что извергаете несколько сотен задач)
StarWind0
16

Если вы хотите выполнять вычисления каждые x секунд, вам, вероятно, следует запланировать a Runnableна Handler(with postDelayed()), и это Runnableдолжно начаться в текущем потоке пользовательского интерфейса. Если вы хотите запустить его в другом потоке, используйте HandlerThread. AsyncTask нам проще использовать, но не лучше обработчика.

MrSnowflake
источник
7

Обработчик связан с основным потоком приложения. он обрабатывает и планирует сообщения и исполняемые файлы, отправляемые из фоновых потоков в основной поток приложения.

AsyncTask предоставляет простой метод обработки фоновых потоков для обновления пользовательского интерфейса, не блокируя его трудоемкими операциями.

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

Вы можете рассмотреть возможность использования AsyncTask, если хотите легко и удобно обмениваться параметрами (таким образом, обновляя пользовательский интерфейс) между основным потоком приложения и фоновым потоком.

secretlm
источник
3
Вы можете создать свой собственный обработчик, связанный с другим потоком.
Aleksejs Mjaliks
Обработчик не обязательно привязан к основному потоку (потоку пользовательского интерфейса). Он привязан к потоку, в котором он был создан, и обрабатывает сообщения или выполняемые объекты, которые поступают в очередь сообщений этого потока. Он также может отправлять объекты Message и Runnable в эту очередь сообщений потока.
azec-pdx
2

AsyncTaskпредполагает, что вы что-то сделаете в потоке пользовательского интерфейса после завершения некоторой фоновой работы. Кроме того, вы можете выполнить его только один раз (после этого его статус будет, FINISHEDи вы получите исключение, пытающееся выполнить его еще раз). К тому же гибкость его использования невелика. Да, можно использовать THREAD_POOL_EXECUTORдля параллельного выполнения, но усилия могут быть не достойными.

Handlerне предполагает ничего, кроме обработки Runnables и Messages. Кроме того, его можно запускать сколько угодно раз . Вы можете решить, к какому потоку он должен быть присоединен, как он взаимодействует с другими обработчиками, возможно, с их помощью HandlerThread. Таким образом, он намного более гибкий и подходит для повторяющейся работы.

Проверьте различные виды Handlerпримеров здесь .

Ломжа
источник
0

Это лучший вопрос на собеседовании. AsyncTask - они используются для разгрузки потока пользовательского интерфейса и выполнения задач в фоновом режиме. Обработчики - Android dosent имеет прямой способ связи между пользовательским интерфейсом и фоновым потоком. Обработчики должны использоваться для отправки сообщения или запускаться через очередь сообщений.

Таким образом, AsyncTasks используются там, где задачи должны выполняться в фоновом режиме, а обработчики используются для связи между пользовательским интерфейсом и фоновым потоком.

саубхагья дас
источник
0

doInBackground - в основном работает в другом потоке. onPostExecute - публикует результаты в потоке пользовательского интерфейса и внутренне отправляет сообщение обработчику основного потока. Основной поток пользовательского интерфейса уже имеет связанный с ним цикл и обработчик.

В общем, если вам нужно выполнить какую-то фоновую задачу, используйте AsyncTask. Но в конечном итоге, если что-то нужно обновить в пользовательском интерфейсе, он будет использовать обработчик основного потока.

Шино Гоял
источник