Handler vs AsyncTask

128

Nie wiem, kiedy można wybrać AsyncTask zamiast Handler. Powiedzmy, że mam kod, który chcę uruchamiać co n sekund, który zaktualizuje interfejs użytkownika. Dlaczego miałbym wybierać jedną z nich?

Steve
źródło
1
Stało się to bardziej skomplikowane w przypadku AsyncTaskLoaders. Więcej informacji znajdziesz na stackoverflow.com/q/7120813/969325 .
Warpzit,

Odpowiedzi:

75

IMO, AsyncTask został napisany, aby zapewnić wygodny, łatwy w użyciu sposób na przetwarzanie w tle w aplikacjach na Androida, bez zbytniego martwienia się o szczegóły niskiego poziomu (wątki, pętle wiadomości itp.). Zapewnia metody wywołania zwrotnego, które pomagają planować zadania, a także łatwo aktualizować interfejs użytkownika, gdy jest to wymagane.

Należy jednak pamiętać, że korzystając z AsyncTask, programista poddaje się swoim ograniczeniom, które wynikały z decyzji projektowych, które podjął autor klasy. Na przykład niedawno dowiedziałem się, że istnieje ograniczenie liczby zadań, które można zaplanować za pomocą AsyncTasks.

Handler jest bardziej przejrzysty i prawdopodobnie daje większą swobodę; więc jeśli chcesz mieć większą kontrolę nad rzeczami, wybierz Handler, w przeciwnym razie AsynTask będzie działał dobrze.

Samuh
źródło
Zgadza się. Używałem AsyncTasks do wszystkich operacji w tle w moim projekcie. W pewnym momencie zacząłem osiągać maksymalny limit zadań, więc moje zadania zaczynały się dopiero po zakończeniu kolejnego. W końcu musiałem zmienić całą swoją strukturę, aby przestać używać asynctask i uniknąć osiągnięcia tego ograniczenia.
tbraun
5
Począwszy od Honeycomb, AsyncTaskssą wykonywane na jednym wątku, więc nie ma już równoległości. Nadal możesz uruchomić je w równoległej Executorimplementacji.
MrSnowflake
64

Moja praktyczna zasada brzmi:

  • Jeśli robisz coś izolowanego, związanego z interfejsem użytkownika, na przykład pobieranie danych do przedstawienia na liście, użyj AsyncTask.

  • Jeśli wykonujesz wiele powtarzających się zadań, na przykład pobieranie wielu obrazów, które mają być wyświetlane ImageViews(jak pobieranie miniatur) podczas pobierania, użyj kolejki zadań z Handler.

alexanderblom
źródło
Program obsługi jest na poziomie API 1, a ASYNCTASK na poziomie API 3. Czy za jakąkolwiek cenę zostanie wycofany? ponieważ koncentruję się na przenoszeniu aplikacji ze starszych wersji do 2.2 i 2.3 ..
yokks,
10
Żadne z nich nie zostanie wkrótce wycofane. Handler nigdy nie będzie przestarzały, ponieważ interfejs użytkownika jest zasadniczo zbudowany wokół niego.
alexanderblom
Czy nie powinieneś używać modułu ładującego do ładowania danych, które mają być prezentowane przez interfejs użytkownika?
nbarraille
19

Zawsze staraj się unikać używania AsyncTask, jeśli to możliwe, głównie z następujących powodów:

  • AsyncTask nie jest gwarantowane do uruchomienia, ponieważ istnieje podstawowa pula wątków i maksymalny rozmiar ustawiony przez system, a jeśli utworzysz zbyt wiele zadań asynchronicznych, zostaną one ostatecznie zniszczone

  • AsyncTask może zostać automatycznie zakończony, nawet podczas działania, w zależności od cyklu życia działania i nie masz nad nim kontroli

  • Metody AsyncTask działające w wątku interfejsu użytkownika, takie jak onPostExecute, mogą być wykonywane, gdy działanie, do którego się odnosi, nie jest już widoczne lub prawdopodobnie znajduje się w innym stanie układu, na przykład po zmianie orientacji.

Podsumowując, nie powinieneś używać metod połączonych z UIThread w AsyncTask, co jest jego główną zaletą !!! Ponadto powinieneś wykonywać tylko niekrytyczne prace na doInBackground. Przeczytaj ten wątek, aby uzyskać więcej informacji na temat tych problemów:

Czy AsyncTask jest naprawdę wadliwy koncepcyjnie, czy po prostu czegoś mi brakuje?

Podsumowując, spróbuj preferować używanie IntentServices, HandlerThread lub ThreadPoolExecutor zamiast AsyncTask, gdy którykolwiek z wyżej wymienionych problemów może być dla Ciebie problemem. Oczywiście będzie to wymagało więcej pracy, ale Twoja aplikacja będzie bezpieczniejsza.

type-a1pha
źródło
Tak, spędziłem dużo czasu żałując wielu zastosowań AsyncTasks. Wydają się świetne, ale ... tak wiele problemów!
SMBiggs
6
Przepraszam, że tak mocno publikuję przeciwko twoim punktom, ale nie mogę pozwolić, aby twój słaby styl wpływał na Androida. Punkt pierwszy. NIE powinieneś mieć tak wielu uruchomionych wątków. Jeśli się na to natkniesz, twoja architektura to foobar. Punkt 2. Jak do licha… OK, tak, wszystko w Androidzie jest grą darmową dla śmieciarza… Można by zobaczyć tylko abserdalne zachowanie, jak opisano powyżej, w niektórych ściśle zadaniowych przypadkach. Punkt 3. Zarządzanie swoim zadaniem, aby nie być niegrzecznym, to umiejętność początkująca. Albo zabijasz go, gdy wywołujesz onPause, albo odpowiednio odłączasz się i odpowiednio podłączasz.
StarWind0
1
vogella.com/tutorials/AndroidBackgroundProcessing/article.html To wszystko, czego potrzebujesz, aby nauczyć się poprawnie wykonywać zadania bez powyższych problemów (zakładając, że nie robisz czegoś takiego jak
wypluwanie
16

Jeśli chcesz wykonywać obliczenia co x sekund, prawdopodobnie powinieneś zaplanować a Runnablena Handler(z postDelayed()) i Runnablepowinno to rozpocząć się w bieżącym wątku interfejsu użytkownika. Jeśli chcesz rozpocząć go w innym wątku, użyj HandlerThread. AsyncTask jest dla nas łatwiejszy w użyciu, ale nie lepszy niż handler.

MrSnowflake
źródło
7

Handler jest powiązany z głównym wątkiem aplikacji. obsługuje i planuje komunikaty i elementy uruchomieniowe wysyłane z wątków w tle do głównego wątku aplikacji.

AsyncTask zapewnia prostą metodę obsługi wątków w tle w celu zaktualizowania interfejsu użytkownika bez blokowania go przez czasochłonne operacje.

Odpowiedź jest taka, że ​​oba mogą być używane do aktualizowania interfejsu użytkownika z wątków w tle, różnica byłaby w scenariuszu wykonywania. Możesz rozważyć użycie modułu obsługi, jeśli chcesz publikować opóźnione wiadomości lub wysyłać wiadomości do MessageQueue w określonej kolejności.

Możesz rozważyć użycie AsyncTask, jeśli chcesz w łatwy i wygodny sposób wymienić parametry (w ten sposób aktualizując interfejs użytkownika) między głównym wątkiem aplikacji a wątkiem w tle.

secretlm
źródło
3
Możesz stworzyć swój własny Handler powiązany z innym Wątkiem.
Aleksejs Mjaliks
Program obsługi niekoniecznie jest powiązany z głównym wątkiem (wątkiem interfejsu użytkownika). Jest on powiązany z wątkiem, w którym został utworzony, i obsługuje komunikaty lub elementy Runnable, które docierają do tej kolejki komunikatów wątku. Może również wysyłać obiekty Message i Runnable do tej kolejki komunikatów wątku.
azec-pdx
2

AsyncTaskzakłada, że ​​po zakończeniu niektórych prac w tle zrobisz coś w wątku interfejsu użytkownika. Ponadto, można go wykonać tylko raz (po tym, jego stan jest FINISHEDa dostaniesz wyjątek próbuje wykonać go jeszcze raz). Również elastyczność korzystania z niego to niewiele. Tak, możesz użyć THREAD_POOL_EXECUTORdo równoległego wykonania, ale wysiłek może nie być wart.

Handlernie zakłada niczego poza obsługą Runnables i Messages. Można go również uruchamiać dowolną liczbę razy . Możesz dowolnie zdecydować, do którego wątku ma być dołączony, jak komunikuje się z innymi programami obsługi, być może z ich pomocą HandlerThread. Jest więc znacznie bardziej elastyczny i nadaje się do powtarzalnej pracy.

Sprawdzać różnego rodzaju Handlerprzykładów tutaj .

łomża
źródło
0

To najlepsze pytanie do rozmowy kwalifikacyjnej, które jest zadawane. AsyncTask - służą do odciążania wątku interfejsu użytkownika i wykonywania zadań w tle. Teleskopowe - Android dosent mają bezpośredni sposób komunikacji między UI i wątku tła. Programy obsługi muszą być używane do wysyłania wiadomości lub uruchamiane przez kolejkę komunikatów.

Dlatego AsyncTasks są używane tam, gdzie zadania muszą być wykonywane w tle, a programy obsługi są używane do komunikacji między interfejsem użytkownika a wątkiem w tle.

saubhagya das
źródło
0

doInBackground - w zasadzie działa w innym wątku. onPostExecute - umieszcza wyniki w wątku UI i wewnętrznie wysyła wiadomość do programu obsługi głównego wątku. Główny wątek interfejsu użytkownika ma już powiązany z nim looper i handler.

Zasadniczo, jeśli musisz wykonać jakieś zadanie w tle, użyj AsyncTask. Ale ostatecznie, jeśli coś musi zostać zaktualizowane w interfejsie użytkownika, będzie używać programu obsługi głównego wątku.

Shinoo Goyal
źródło