Dostałem nieco mylić o różnicach między Handlers
, AsyncTask
a Threads
w Androidzie. Przeczytałem sporo blogów i pytań tutaj w StackOverflow.
Handler
to wątki w tle, które zapewniają komunikację z interfejsem użytkownika. Na przykład aktualizacja paska postępu powinna odbywać się za pośrednictwem Handler
. Korzystanie z programów obsługi ma tę zaletę MessagingQueues
, że jeśli chcesz planować wiadomości lub aktualizować wiele elementów interfejsu użytkownika lub wykonywać powtarzające się zadania.
AsyncTask
są podobne, w rzeczywistości korzystają z nich Handler
, ale nie działają w wątku interfejsu użytkownika, więc dobrze nadaje się do pobierania danych, na przykład usług sieciowych. Później możesz wchodzić w interakcje z interfejsem użytkownika.
Thread
nie może jednak wchodzić w interakcje z interfejsem użytkownika, zapewnia bardziej „podstawowe” wątki, a brakuje wszystkich abstrakcji AsyncTask
.
Chciałbym jednak mieć uruchomione połączenie z gniazdem. Czy należy to uruchomić w module obsługi, wątku, czy nawet w AsyncTask
? Interakcja interfejsu użytkownika w ogóle nie jest konieczna. Czy ma to wpływ na wydajność, której używam?
Tymczasem dokumentacja została znacznie ulepszona.
Handler
nie jest wątkiem i niczego nie wykonuje. To tylko sposób na bezpieczne przekazywanie wiadomości z jednego wątku do kolejki komunikatów innego wątku . Tak więc normalnie (przynajmniej) muszą zostać utworzone dwa wątki, które mogą następnie używać modułu obsługi, ale moduł obsługi nie może samodzielnie wykonać niczego.Odpowiedzi:
W samouczku na temat przetwarzania w tle w systemie Android za pomocą programów obsługi, AsyncTask i Loaders na stronie Vogella:
Handler
Klasy mogą być wykorzystane do rejestracji do wątku i zapewnia prosty kanał do przesyłania danych do tego wątku.AsyncTask
Klasy obudowuje stworzenie procesu tła i synchronizacji z głównym gwintem. Obsługuje również raportowanie postępu uruchomionych zadań.A
Thread
jest w zasadzie podstawowym elementem wielowątkowości, z którego programista może korzystać z następującą wadą:A jeśli chodzi o
AsyncTask
, jak to ujęła Dokumentacja programisty Androida :Aktualizacja maj 2015: Znalazłem doskonałą serię wykładów na ten temat.
Ważne: jeśli jesteś w punkcie, w którym rozważasz
AsyncTask
rozwiązanie problemów z wątkami, powinieneś najpierw sprawdzić, czyReactiveX/RxAndroid
jest bardziej odpowiedni wzorzec programowania. Bardzo dobrym źródłem do uzyskania przeglądu jest Nauka RxJava 2 dla Androida na przykład .źródło
Jeśli spojrzymy na kod źródłowy, zobaczymy
AsyncTask
iHandler
jest napisany wyłącznie w Javie. (Są jednak wyjątki. Ale to nie jest ważny punkt)Więc nie ma magii w
AsyncTask
lubHandler
. Zajęcia te ułatwiają nam życie jako programista.Na przykład: jeśli program A wywołuje metodę A (), metoda A () może działać w innym wątku z programem A. Możemy łatwo zweryfikować, wykonując następujący kod:
Dlaczego powinniśmy używać nowego wątku do niektórych zadań? Możesz go znaleźć w Google. Wiele powodów, np .: ciężkie podnoszenie, długotrwałe prace.
Więc, jakie są różnice między
Thread
,AsyncTask
iHandler
?AsyncTask
iHandler
są napisane w Javie (wewnętrznie używają aThread
), więc wszystko, co możemy zrobić z,Handler
lub teżAsyncTask
możemy osiągnąć, używającThread
też.Co może
Handler
iAsyncTask
naprawdę może pomóc?Najbardziej oczywistym powodem jest komunikacja między wątkiem wywołującym a wątkiem roboczym. ( Wątek dzwoniącego : Wątek, który wywołuje Wątek roboczy w celu wykonania niektórych zadań. Wątek dzwoniącego niekoniecznie musi być wątkiem interfejsu użytkownika). Oczywiście możemy komunikować się między dwoma wątkami na inne sposoby, ale istnieje wiele wad (i niebezpieczeństw) ze względu na bezpieczeństwo wątków.
Dlatego powinniśmy użyć
Handler
iAsyncTask
. Klasy te wykonują za nas większość pracy, musimy tylko wiedzieć, które metody zastąpić.Różnica między
Handler
iAsyncTask
to: Użyj,AsyncTask
gdy wątek dzwoniącego jest wątkiem interfejsu użytkownika . Tak mówi dokument Android:Chcę podkreślić dwie kwestie:
1) Łatwe korzystanie z wątku interfejsu użytkownika (więc użyj, gdy wątkiem wywołującym jest wątek interfejsu użytkownika).
2) Nie trzeba manipulować programami obsługi. (oznacza: Możesz użyć modułu obsługi zamiast AsyncTask, ale AsyncTask jest łatwiejszą opcją).
W tym poście jest wiele rzeczy, których jeszcze nie powiedziałem, na przykład: co to jest wątek interfejsu użytkownika lub dlaczego jest to łatwiejsze. Musisz znać metody każdej klasy i korzystać z niej, w pełni zrozumiesz powód.
@: kiedy czytasz dokument Androida, zobaczysz:
Ten opis może początkowo wydawać się dziwny. Musimy tylko zrozumieć, że każdy wątek ma każdą kolejkę wiadomości (jak lista rzeczy do zrobienia), a wątek weźmie każdą wiadomość i zrobi to, dopóki kolejka wiadomości nie będzie pusta (tak jak kończymy naszą pracę i kładziemy się spać). Tak więc, gdy się
Handler
komunikuje, po prostu wysyła wiadomość do wątku dzwoniącego i będzie czekał na przetworzenie.Skomplikowane? Pamiętaj tylko, że
Handler
może bezpiecznie komunikować się z wątkiem dzwoniącego.źródło
Po dogłębnym spojrzeniu jest to proste.
AsyncTask
:Jest to prosty sposób na użycie wątku bez wiedzy na temat modelu wątku Java .
AsyncTask
daje różne wywołania zwrotne odpowiednio do wątku roboczego i głównego wątku.Użyj do małych operacji oczekiwania, takich jak:
Handler
:Gdy instalujemy aplikację w systemie Android, tworzy ona wątek dla tej aplikacji o nazwie MAIN UI Thread. Wszystkie działania przebiegają w tym wątku. Zgodnie z regułą modelu pojedynczego wątku Androida nie możemy uzyskać dostępu do elementów interfejsu użytkownika (bitmapy, widoku tekstu itp.) Bezpośrednio dla innego wątku zdefiniowanego w ramach tego działania.
Moduł obsługi umożliwia komunikację z wątkiem interfejsu użytkownika z innych wątków w tle. Jest to przydatne w Androidzie, ponieważ Android nie pozwala innym wątkom komunikować się bezpośrednio z wątkiem interfejsu użytkownika. Program obsługi może wysyłać i przetwarzać obiekty Message i Runnable powiązane z MessageQueue wątku. Każda instancja modułu obsługi jest powiązana z jednym wątkiem i kolejką komunikatów tego wątku. Gdy tworzony jest nowy moduł obsługi, jest on powiązany z kolejką wątków / komunikatów tworzącego go wątku.
To najlepiej pasuje do:
Thread
:Czas porozmawiać o wątku.
Wątek jest rodzicem zarówno
AsyncTask
iHandler
. Oba używają wątku wewnętrznie, co oznacza, że możesz również stworzyć swój własny model wątku, jakAsyncTask
iHandler
, ale to wymaga dobrej znajomości implementacji wielowątkowości Javy .źródło
An
AsyncTask
służy do wykonywania obliczeń w tle i publikowania wyników w wątku interfejsu użytkownika (z opcjonalnymi aktualizacjami postępu). Ponieważ nie interesujesz się interfejsem użytkownika, aHandler
lubThread
wydaje się bardziej odpowiednie.Można tarło tło
Thread
i przekazać wiadomości z powrotem do głównego wątku za pomocąHandler
„spost
metody.źródło
Wątek
Android obsługuje standardowe wątki Java . Możesz użyć standardowych wątków i narzędzi z pakietu „
java.util.concurrent
”, aby umieścić działania w tle. Jedynym ograniczeniem jest to, że nie można bezpośrednio zaktualizować interfejsu użytkownika z procesu działającego w tle.Jeśli musisz zaktualizować interfejs użytkownika z zadania w tle, musisz użyć niektórych klas specyficznych dla Androida. Możesz użyć klasy „
android.os.Handler
” do tego lub klasy „AsyncTask
”Treser
Klasa „
Handler
” może aktualizować interfejs użytkownika. Uchwyt zapewnia metody odbierania komunikatów i uruchamiania. Aby użyć modułu obsługi, należy go podklasować i zastąpić whandleMessage()
celu przetwarzania komunikatów. Aby przetworzyćRunable
, możesz użyć metodypost();
Potrzebujesz tylko jednego wystąpienia procedury obsługi w swoim działaniu.Wątek może publikować wiadomości za pomocą metody
sendMessage(Message msg)
lubsendEmptyMessage
.AsyncTask
Jeśli masz coś,
Activity
co wymaga pobrania treści lub wykonania operacji, które można wykonać w tle,AsyncTask
możesz zachować responsywny interfejs użytkownika i opublikować postępy w zakresie tych operacji dla użytkownika.Aby uzyskać więcej informacji, możesz przejrzeć te linki.
http://mobisys.in/blog/2012/01/android-threads-handlers-and-asynctask-tutorial/
http://www.slideshare.net/HoangNgoBuu/android-thread-handler-and-asynctask
źródło
Thread
:Możesz użyć nowego
Thread
do długotrwałych zadań w tle bez wpływu na wątek interfejsu użytkownika. W wątku Java nie można aktualizować wątku interfejsu użytkownika.Ponieważ normalny wątek nie jest zbyt przydatny w architekturze Androida, wprowadzono klasy pomocnicze dla wątków.
Odpowiedzi na pytania można znaleźć na stronie dokumentacji wydajności wątków .
Handler :
A
Handler
umożliwia wysyłanie i przetwarzanie wiadomości iRunnable
obiektów powiązanych z wątkiemMessageQueue
. KażdeHandler
wystąpienie jest powiązane z jednym wątkiem i kolejką komunikatów tego wątku.Istnieją dwa główne zastosowania
Handler
:Aby zaplanować komunikaty i programy uruchamiające, które będą wykonywane w przyszłości;
Aby kolejkować akcję, która ma być wykonana w innym wątku niż własny.
AsyncTask :
AsyncTask
umożliwia prawidłowe i łatwe korzystanie z wątku interfejsu użytkownika. Ta klasa umożliwia wykonywanie operacji w tle i publikowanie wyników w wątku interfejsu użytkownika bez konieczności manipulowania wątkami i / lub programami obsługi.Wady:
Domyślnie aplikacja wypycha wszystkie utworzone
AsyncTask
obiekty do jednego wątku. Dlatego są one wykonywane szeregowo i - podobnie jak w przypadku głównego wątku - szczególnie długi pakiet roboczy może blokować kolejkę. Z tego powodu użyj AsyncTask do obsługi elementów roboczych o czasie trwania krótszym niż 5ms .AsyncTask
obiekty są również najczęstszymi sprawcami niejawnych odniesień.AsyncTask
obiekty stanowią również ryzyko związane z wyraźnymi odniesieniami.HandlerThread :
Może być potrzebne bardziej tradycyjne podejście do wykonywania bloku pracy w wątku długo działającym (w przeciwieństwie do AsyncTask, który powinien być używany przy obciążeniu 5 ms ) oraz pewna umiejętność ręcznego zarządzania tym przepływem pracy. Wątek programu obsługi jest w rzeczywistości długo działającym wątkiem, który pobiera pracę z kolejki i działa na niej.
ThreadPoolExecutor :
Ta klasa zarządza tworzeniem grupy wątków, ustala ich priorytety i zarządza rozkładem pracy między tymi wątkami. Gdy obciążenie wzrasta lub maleje, klasa obraca się w górę lub niszczy więcej wątków, aby dostosować się do obciążenia.
Jeśli obciążenie jest większe, a pojedyncze
HandlerThread
nie wystarcza, możesz przejść dalejThreadPoolExecutor
Ponieważ interakcja w interfejsie użytkownika nie jest wymagana, nie możesz iść
AsyncTask
. Normalne wątki nie są zbyt przydatne i dlategoHandlerThread
są najlepszą opcją. Ponieważ musisz zachować połączenie z gniazdem, moduł obsługi głównego wątku nie jest w ogóle przydatny. Utwórz aHandlerThread
i zdobądźHandler
z looper'aHandlerThread
.Jeśli chcesz komunikować się z powrotem w wątku interfejsu użytkownika, możesz użyć jeszcze jednego modułu obsługi do przetworzenia odpowiedzi.
w twoim
Runnable
, możesz dodaćWięcej informacji na temat implementacji można znaleźć tutaj:
Android: Toast w wątku
źródło
Moim zdaniem wątki nie są najskuteczniejszym sposobem wykonywania połączeń przez gniazda, ale zapewniają największą funkcjonalność pod względem uruchamiania wątków. Mówię to, ponieważ z doświadczenia, uruchamianie wątków przez długi czas powoduje, że urządzenia są bardzo gorące i wymagają dużej ilości zasobów. Nawet zwykły
while(true)
telefon nagrzeje telefon w kilka minut. Jeśli powiesz, że interakcja z interfejsem użytkownika nie jest ważna, być możeAsyncTask
jest dobra, ponieważ są one przeznaczone do długotrwałych procesów. To tylko moja opinia na ten temat.AKTUALIZACJA
Proszę zignoruj moją powyższą odpowiedź! Odpowiedziałem na to pytanie w 2011 roku, kiedy byłem znacznie mniej doświadczony w Androidzie niż teraz. Moja odpowiedź powyżej jest myląca i uważana za błędną. Zostawiam to, ponieważ wiele osób skomentowało to poniżej, poprawiając mnie i nauczyłem się mojej lekcji.
Istnieją znacznie lepsze inne odpowiedzi w tym wątku, ale przynajmniej dam mi bardziej odpowiednią odpowiedź. Nie ma nic złego w korzystaniu ze zwykłej Java
Thread
; jednak powinieneś bardzo uważać na to, jak go zaimplementować, ponieważ jego nieprawidłowe wykonanie może być bardzo obciążające procesor (najbardziej zauważalnym objawem może być nagrzewanie się urządzenia).AsyncTask
s są dość idealne do większości zadań, które chcesz uruchomić w tle (typowe przykłady to dyskowe operacje we / wy, połączenia sieciowe i połączenia z bazą danych). NieAsyncTask
należy go jednak używać do szczególnie długich procesów, które mogą wymagać kontynuacji po zamknięciu aplikacji lub przejściu urządzenia w tryb gotowości. Powiedziałbym, że w większości przypadków wszystko, co nie należy do wątku interfejsu użytkownika, można załatwić wAsyncTask
.źródło
AsyncTask
jest przeznaczony do wykonywania w tle nie więcej niż kilku sekund operacji (niezalecane w przypadku megabajtów pobierania plików z serwera lub obliczeniowych zadań procesora, takich jak operacje na plikach we / wy). Jeśli chcesz wykonać długo działającą operację, zdecydowanie zaleca się używanie rodzimych wątków Java. Java oferuje różne klasy związane z wątkami, aby robić to, czego potrzebujesz. SłużyHandler
do aktualizowania wątku interfejsu użytkownika.źródło
źródło
Pozwól, że spróbuję odpowiedzieć na pytanie tutaj z przykładem :) - MyImageSearch [Prosimy odnieść się tutaj do obrazu głównego ekranu aktywności - zawierającego tekst edycji / przycisk wyszukiwania / widok siatki]
Opis MyImageSearch - gdy użytkownik wprowadzi dane w polu edycji tekstu i kliknie przycisk wyszukiwania, przeszukamy obrazy w Internecie za pośrednictwem usług internetowych świadczonych przez flickr (wystarczy się tam zarejestrować, aby uzyskać klucz / tajny token) - do wyszukiwania wysyłamy żądanie HTTP i GET JSON Data w odpowiedzi, zawierające adres URL poszczególnych obrazów, które następnie wykorzystamy do załadowania widoku siatki.
Moja implementacja - w głównym zadaniu zdefiniuję wewnętrzną klasę, która rozszerza AsyncTask o wysyłanie żądania HTTP w metodzie doInBackGround i pobiera odpowiedź JSON oraz aktualizuje moją lokalną ArrayList FlickrItems, której zamierzam użyć do aktualizacji mojego GridView poprzez FlickrAdapter (rozszerza BaseAdapter) i wywołuje adapter.notifyDataSetChanged () w onPostExecute () AsyncTask, aby ponownie załadować widok siatki. Zauważ, że tutaj żądanie HTTP jest wywołaniem blokującym, z powodu którego zrobiłem to za pomocą AsyncTask. I mogę buforować elementy w adapterze, aby zwiększyć wydajność lub zapisać je na karcie SD. Siatka, którą będę pompować w FlickrAdapter zawiera w mojej implementacji pasek postępu i widok obrazu. Poniżej znajdziesz kod dla mainActivity, którego użyłem.
Odpowiedz teraz na pytanie - kiedy już mamy dane JSON do pobierania poszczególnych obrazów, możemy zaimplementować logikę pobierania obrazów w tle za pośrednictwem programów obsługi, wątków lub AsyncTask. Powinniśmy tutaj zauważyć, że ponieważ moje pobrane obrazy muszą być wyświetlane w interfejsie użytkownika / wątku głównym, nie możemy po prostu używać wątków, ponieważ nie mają one dostępu do kontekstu. W FlickrAdapter wybory, które mogłem wymyślić:
Oto kod źródłowy:
Mam nadzieję, że moja długa odpowiedź pomoże w zrozumieniu niektórych drobniejszych szczegółów.
źródło
Zależy, który wybrać, zależy od wymagań
Handler jest najczęściej używany do przełączania z innego wątku na główny wątek, Handler jest podłączony do looper'a, na którym umieszcza swoje uruchamialne zadanie w kolejce. Więc jeśli jesteś już w innym wątku i przełączasz się na główny wątek, potrzebujesz uchwytu zamiast zadania asynchronicznego lub innego wątku
Jeśli moduł obsługi utworzony w wątku innym niż główny, który nie jest looperem, nie będzie dawał błędu, gdy uchwyt zostanie utworzony, wątek ten musi zostać zmieniony
AsyncTask służy do wykonywania kodu przez kilka sekund, który działa w wątku w tle i podaje wynik wątkowi głównemu ** * Ograniczenia AsyncTask 1. Zadanie Async nie jest powiązane z cyklem życia działania i działa dalej, nawet jeśli jego aktywność zostanie zniszczona, a moduł ładujący nie nie mają tego ograniczenia 2. Wszystkie zadania asynchroniczne mają ten sam wątek tła do wykonania, co również wpływa na wydajność aplikacji
Wątek jest również używany w aplikacji do pracy w tle, ale nie ma żadnego wywołania zwrotnego w głównym wątku. Jeśli wymaganie pasuje do niektórych wątków zamiast jednego wątku i które muszą dawać zadanie wiele razy, to wykonawca puli wątków jest lepszą opcją. Wymaganie ładowania obrazu z wielu adresów URL, takich jak glide.
źródło
Wątek
Po uruchomieniu aplikacji tworzony jest proces wykonywania kodu. Aby efektywnie korzystać z zasobów obliczeniowych, w procesie można uruchamiać wątki, aby jednocześnie wykonywać wiele zadań. Wątki pozwalają więc tworzyć wydajne aplikacje dzięki wydajnemu wykorzystaniu procesora bez przestoju.
W Androidzie wszystkie komponenty są uruchamiane w jednym wątku głównym. Kolejki systemowe w systemie Android wykonują je kolejno w głównym wątku. Po wykonaniu długo działających zadań aplikacja przestaje odpowiadać.
Aby temu zapobiec, możesz tworzyć wątki robocze i uruchamiać zadania w tle lub zadania długo działające.
Treser
Ponieważ Android korzysta z modelu jednowątkowego, komponenty interfejsu użytkownika są tworzone jako bezpieczne dla wątków, co oznacza, że tylko utworzony przez nich wątek powinien mieć do nich dostęp, co oznacza, że komponent interfejsu powinien być aktualizowany tylko w głównym wątku. Ponieważ składnik interfejsu użytkownika działa w głównym wątku, zadania uruchamiane w wątkach roboczych nie mogą modyfikować składników interfejsu użytkownika. Tutaj pojawia się Handler. Program obsługi za pomocą Looper może łączyć się z nowym wątkiem lub istniejącym wątkiem i uruchamiać kod, który zawiera w połączonym wątku.
Program obsługi umożliwia komunikację między wątkami. Za pomocą modułu obsługi wątek w tle może wysyłać do niego wyniki, a moduł obsługi podłączony do głównego wątku może aktualizować komponenty interfejsu użytkownika w głównym wątku.
AsyncTask
AsyncTask dostarczany przez Androida wykorzystuje zarówno wątek, jak i moduł obsługi, aby ułatwić uruchamianie prostych zadań w tle i łatwą aktualizację wyników z wątku w tle do głównego.
Przykłady można znaleźć w wątkach Androida, module obsługi, asynctask i pulach wątków .
źródło
Handler
- jest środkiem komunikacji między wątkami. W Androidzie służy głównie do komunikowania się z głównym wątkiem poprzez tworzenie i wysyłanie wiadomości za pomocą modułu obsługiAsyncTask
- służy do wykonywania długo działających aplikacji w wątku w tle. Za pomocą nAsyncTask
możesz wykonać operację w wątku w tle i uzyskać wynik w głównym wątku aplikacji.Thread
- jest procesem lekkim, aby osiągnąć współbieżność i maksymalne wykorzystanie procesora. W Androidzie możesz używać wątku do wykonywania czynności, które nie dotykają interfejsu użytkownika aplikacjiźródło