Jestem nowy na Androida. Chcę wiedzieć, co Looper
robi klasa, a także jak z niej korzystać. Przeczytałem dokumentację klasy Android Looper, ale nie jestem w stanie jej w pełni zrozumieć. Widziałem go w wielu miejscach, ale nie mogłem zrozumieć jego celu. Czy ktoś może mi pomóc, określając cel, Looper
a także podając prosty przykład, jeśli to możliwe?
android
multithreading
android-looper
Khawar Raza
źródło
źródło
Odpowiedzi:
Co to jest Looper?
Looper to klasa używana do wykonywania komunikatów (Runnables) w kolejce. Normalne wątki nie mają takiej kolejki, np. Prosty wątek nie ma żadnej kolejki. Wykonuje się raz, a po zakończeniu wykonywania metody wątek nie uruchomi kolejnej wiadomości (Runnable).
Gdzie możemy skorzystać z klasy Looper?
Jeśli ktoś chce wykonać wiele komunikatów (Runnables), powinien użyć klasy Looper, która jest odpowiedzialna za tworzenie kolejki w wątku. Na przykład pisząc aplikację, która pobiera pliki z Internetu, możemy użyć klasy Looper, aby umieścić pliki do pobrania w kolejce.
Jak to działa?
Istnieje
prepare()
metoda przygotowania Looper. Następnie możesz użyćloop()
metody do utworzenia pętli komunikatów w bieżącym wątku, a teraz Twój Looper jest gotowy do wykonania żądań w kolejce, dopóki nie opuścisz pętli.Oto kod, dzięki któremu możesz przygotować Looper.
źródło
Możesz lepiej zrozumieć, czym jest Looper w kontekście GUI. Looper ma zrobić 2 rzeczy.
1) Looper przekształca normalny wątek , który kończy się po powrocie metody run (), w coś działającego nieprzerwanie do momentu uruchomienia aplikacji na Androida , co jest potrzebne w środowisku GUI (technicznie rzecz biorąc, nadal kończy się, gdy metoda run () powróci. Ale pozwól mi wyjaśnij, co mam na myśli poniżej).
2) Looper zapewnia kolejkę, w której zadania do wykonania są kolejkowane, co jest również potrzebne w środowisku GUI.
Jak zapewne wiesz, po uruchomieniu aplikacji system tworzy dla niej wątek wykonawczy, zwany „głównym”, a aplikacje na Androida zwykle domyślnie działają w całości na jednym wątku, domyślnie „głównym wątku”. Ale główny wątek nie jest jakimś tajnym, specjalnym wątkiem . To zwykły wątek podobny do wątków, które tworzysz
new Thread()
kodu, co oznacza, że kończy się po powrocie metody run ()! Pomyśl o poniższym przykładzie.Teraz zastosujmy tę prostą zasadę do aplikacji na Androida. Co by się stało, gdyby aplikacja na Androida działała na normalnym wątku? Wątek o nazwie „main” lub „UI” lub cokolwiek uruchamia twoją aplikację i rysuje cały interfejs użytkownika. Zatem pierwszy ekran jest wyświetlany użytkownikom. Co teraz? Główny wątek kończy się? Nie, nie powinno. Powinien poczekać, aż użytkownicy coś zrobią, prawda? Ale jak możemy osiągnąć takie zachowanie? Cóż, możemy spróbować z
Object.wait()
lubThread.sleep()
. Na przykład główny wątek kończy swoje początkowe zadanie, aby wyświetlić pierwszy ekran i śpi. Budzi się, co oznacza przerwanie, gdy pobierane jest nowe zadanie. Jak dotąd tak dobrze, ale w tej chwili potrzebujemy struktury danych przypominającej kolejkę do obsługi wielu zadań. Pomyśl o przypadku, gdy użytkownik dotknie ekranu szeregowo, a zakończenie zadania zajmuje więcej czasu. Musimy więc mieć strukturę danych, aby przechowywać zadania do wykonania według kolejności zgłoszeń. Można również sobie wyobrazić, że implementacja wątku działającego i przetwarzającego, gdy dotrze do niego przy użyciu przerwania, nie jest łatwa i prowadzi do złożonego i często niemożliwego do utrzymania kodu. W tym celu wolelibyśmy stworzyć nowy mechanizm i na tym właśnie polega Looper . Oficjalny dokument klasy Loopermówi: „Wątki domyślnie nie mają z nimi powiązanej pętli komunikatów”, a Looper jest klasą „używaną do uruchamiania pętli komunikatów dla wątku”. Teraz możesz zrozumieć, co to znaczy.Aby to wyjaśnić, sprawdźmy kod, w którym główny wątek jest transformowany. Wszystko to dzieje się w klasie ActivityThread . W metodzie main () możesz znaleźć poniższy kod, który zamienia normalny główny wątek w coś, czego potrzebujemy.
i
Looper.loop()
metoda zapętla się w nieskończoność i usuwa z kolejki komunikat i przetwarza pojedynczo:Zasadniczo Looper to klasa stworzona w celu rozwiązania problemu występującego w środowisku GUI. Ale tego rodzaju potrzeby mogą się również zdarzyć w innej sytuacji. W rzeczywistości jest to dość znany wzorzec dla aplikacji wielowątkowych i możesz dowiedzieć się więcej na ten temat w „ Concurrent Programming in Java ” Douga Lei (zwłaszcza rozdział 4.1.4 „Wątki robocze” byłby pomocny). Można również sobie wyobrazić, że ten rodzaj mechanizmu nie jest unikalny w systemie Android, ale wszystkie ramy GUI mogą wymagać nieco podobnego do tego. Prawie taki sam mechanizm można znaleźć w frameworku Java Swing.
źródło
Looper pozwala na wykonywanie zadań sekwencyjnie na jednym wątku. I przewodnik określa te zadania, które musimy wykonać. Jest to typowy scenariusz, który próbuję zilustrować w tym przykładzie:
Teraz możemy użyć modułu obsługi w innych wątkach (powiedzmy wątek interfejsu użytkownika), aby opublikować zadanie w Looper do wykonania.
W wątku interfejsu użytkownika mamy domyślny Looper, który pozwala nam obsługiwać wiadomości w wątku interfejsu użytkownika.
źródło
Android
Looper
jest opakowaniem, aby dołączyćMessageQueue
doThread
i zarządza przetwarzania kolejki. Wygląda to bardzo tajemniczo w dokumentacji Androida i wiele razy możemy napotkaćLooper
powiązane problemy z dostępem do interfejsu użytkownika. Jeśli nie rozumiemy podstaw, staje się bardzo trudny w obsłudze.Oto artykuł , który wyjaśnia,
Looper
cykl życiowy, jak go używać i wykorzystanieLooper
wHandler
Looper = Wątek + Komunikat
źródło
Definicja Looper & Handler:
Looper jest klasą, która zamienia wątek w wątek rurociągu, a moduł obsługi udostępnia mechanizm wypychania zadań z dowolnego innego wątku.
Detale:
Tak więc wątek PipeLine jest wątkiem, który może przyjmować więcej zadań z innych wątków za pośrednictwem modułu obsługi.
Looper jest nazwany tak dlatego, że wykonuje pętlę - wykonuje kolejne zadanie, wykonuje go, a następnie wykonuje następny i tak dalej. Moduł obsługi nazywany jest modułem obsługi, ponieważ jest używany do obsługi lub akceptowania następnego zadania za każdym razem z dowolnego innego wątku i przekazywany do Looper (Thread lub PipeLine Thread).
Przykład:
Doskonałym przykładem wątku Looper and Handler lub PipeLine jest pobranie więcej niż jednego obrazu lub przesłanie ich na serwer (HTTP) jeden po drugim w jednym wątku zamiast rozpoczynania nowego wątku dla każdego połączenia sieciowego w tle.
Przeczytaj więcej o Looper i Handler oraz definicji wątku rurociągu:
Android Guts: wprowadzenie do pętli i programów obsługi
źródło
Looper posiada
synchronized
MessageQueue
, który jest używany do przetwarzania wiadomości umieszczonych w kolejce.Implementuje
Thread
określony wzorzec przechowywania.Tylko jeden
Looper
naThread
. Kluczowe metody obejmująprepare()
,loop()
iquit()
.prepare()
inicjuje prądThread
jakoLooper
.prepare()
tostatic
metoda wykorzystującaThreadLocal
klasę, jak pokazano poniżej.prepare()
należy wywołać jawnie przed uruchomieniem pętli zdarzeń.loop()
uruchamia pętlę zdarzeń, która czeka, aż Wiadomości dotrą do kolejki komunikatów określonego wątku. Po odebraniu następnego komunikatuloop()
metoda wysyła komunikat do docelowego modułu obsługiquit()
zamyka pętlę zdarzeń. Nie kończy pętli, ale zamiast tego wywołuje specjalną wiadomośćLooper
można zaprogramować wThread
kilku krokachPoszerzać
Thread
Zadzwoń,
Looper.prepare()
aby zainicjować wątek jakoLooper
Utwórz co najmniej jeden
Handler
(e), aby przetwarzać przychodzące wiadomościLooper.loop()
aby przetwarzać wiadomości, dopóki nie pojawi się polecenie zapętleniaquit()
.źródło
Żywotność java Wątek dobiegł końca po zakończeniu
run()
metody. Ten sam wątek nie może zostać ponownie uruchomiony.Looper przekształca normalną
Thread
w pętlę komunikatów. Kluczowe metodyLooper
to:Ten artykuł autorstwa Mindish autorstwa Janishara ładnie wyjaśnia podstawowe pojęcia.
Looper
jest powiązany z wątkiem. Jeśli potrzebujeszLooper
wątku interfejsu użytkownika,Looper.getMainLooper()
zwróci powiązany wątek.Musisz
Looper
być powiązany z osobą zajmującą się obsługą .Looper
,Handler
iHandlerThread
są sposobem Androida na rozwiązanie problemów programowania asynchronicznego.Gdy to zrobisz
Handler
, możesz zadzwonić poniżej API.HandlerThread to przydatna klasa do rozpoczynania nowego wątku, który ma pętlę. Looper może być następnie użyty do stworzenia klas procedur obsługi
W niektórych scenariuszach nie można uruchamiać
Runnable
zadań w wątku interfejsu użytkownika. np. operacje sieciowe: wyślij wiadomość na gniazdo, otwórz adres URL i uzyskaj treść, czytającInputStream
W takich przypadkach
HandlerThread
przydaje się. Można uzyskaćLooper
obiektu zHandlerThread
i utworzyćHandler
naHandlerThread
zamiast głównego wątku.HandlerThread kod będzie tak:
Zobacz poniższy kod na przykład kod:
Android: Toast w wątku
źródło
Zrozumienie wątków Looper
Wątek java Wątek jednostki wykonawczej, która została zaprojektowana do wykonania zadania w metodzie run (), a następnie zakończ:
Ale w Androidzie istnieje wiele przypadków użycia, w których musimy utrzymywać wątek przy życiu i czekać na dane wejściowe / zdarzenia użytkownika np. UI wątek aka
Main Thread
.Główny wątek w Androidzie to wątek Java, który został po raz pierwszy uruchomiony przez JVM przy uruchomieniu aplikacji i działa dalej, dopóki użytkownik nie zdecyduje się go zamknąć lub napotka nieobsługiwany wyjątek.
Teraz należy zauważyć, że chociaż głównym wątkiem jest wątek Java, wciąż słucha on zdarzeń użytkownika i rysuje 60 klatek na sekundę na ekranie, a mimo to nie umrze po każdym cyklu. jak to jest
Wątki domyślnie nie mają powiązanej z nimi pętli komunikatów, ale można ją przypisać poprzez wywołanie Looper.prepare () w metodzie run, a następnie wywołanie Looper.loop ().
Jeśli chcesz głębiej dowiedzieć się, jak Looper zarządza
Message
kolejką obiektów, możesz spojrzeć na kod źródłowyLooperclass
:Poniżej znajduje się przykład, w jaki sposób możesz stworzyć klasę
Looper Thread
i komunikować się z niąActivity
za pomocąLocalBroadcast
Zastosowanie :
Czy zamiast tego możemy użyć zadania asynchronicznego lub usług intencyjnych?
Zadania asynchroniczne są zaprojektowane do wykonywania krótkich operacji w tle i dostarczania postępów i wyników w wątku interfejsu użytkownika. Zadania asynchroniczne mają takie ograniczenia, że nie można utworzyć więcej niż 128 zadań asynchronicznych i
ThreadPoolExecutor
zezwalają na maksymalnie 5 zadań asynchronicznych .IntentServices
są również zaprojektowane do wykonywania zadań w tle przez nieco dłuższy czas i możnaLocalBroadcast
się z nimi komunikowaćActivity
. Ale usługi ulegają zniszczeniu po wykonaniu zadania. Jeśli chcesz, aby działał przez dłuższy czas, niż musisz robić, do cholery, jakwhile(true){...}
.Inne znaczące przypadki użycia Looper Thread:
Służy do komunikacji z gniazdem dwukierunkowym, gdy serwer nasłuchuje gniazda klienta i zapisuje potwierdzenie
Przetwarzanie bitmapy w tle. Przekaż adres URL obrazu do wątku Looper, a on zastosuje efekty filtrów i zapisze go w lokalizacji tempe rory, a następnie wyemituje tymczasową ścieżkę obrazu.
źródło
Ta odpowiedź nie ma nic wspólnego z pytaniem, ale użycie looper i sposób, w jaki ludzie stworzyli moduł obsługi i looper we WSZYSTKICH tutaj odpowiedziach, są po prostu złą praktyką (choć niektóre wyjaśnienia są poprawne), muszę to opublikować:
i dla pełnego wdrożenia
źródło
Lepszym przykładem jest obsługa wielu elementów w dół lub przesyłanych w usłudze .
Handler
iAsnycTask
są często używane do propagowania zdarzeń / komunikatów między interfejsem użytkownika (wątkiem) a wątkiem roboczym lub do opóźniania działań. Są więc bardziej związane z interfejsem użytkownika.A
Looper
obsługuje zadania ( Runnables, Futures ) w kolejce powiązanej z wątkami w tle - nawet bez interakcji użytkownika lub wyświetlanego interfejsu użytkownika (aplikacja pobiera plik w tle podczas połączenia).źródło
Z DOCS
Looper
Looper
Klasa używana do uruchomienia pętli komunikatów dlathread
. Wątki domyślnie nie są powiązane z pętlą komunikatów; aby go utworzyć, należy wywołaćprepare()
wątek, który ma uruchomić pętlę, a następnieloop()
przetworzyć komunikaty do momentu zatrzymania pętli.Looper
to pętla obsługi komunikatów:MessageQueue
, która zawiera komunikaty listy. Ważną postacią Looper jest to, że jest on powiązany z wątkiem, w którym Looper jest tworzony.Looper
Nazywa się tak dlatego, że wykonuje pętlę - wykonuje kolejne zadanie, wykonuje go, a następnie wykonuje następny i tak dalej.Handler
Nazywamy obsługi dlatego, że ktoś nie mógł wymyślić lepszej nazwyLooper
to klasa Java w interfejsie użytkownika Androida, która wraz z klasą Handler do przetwarzania zdarzeń interfejsu użytkownika, takich jak kliknięcia przycisków, przerysowywanie ekranu i przełączanie orientacji.Wątek otrzymuje a
Looper
iMessageQueue
dzwoniLooper.prepare()
po jego uruchomieniu.Looper.prepare()
identyfikuje wątek wywołujący, tworzy Looper iMessageQueue
obiekt oraz kojarzy wątekPRZYKŁADOWY KOD
Aby uzyskać więcej informacji, sprawdź poniższy post
źródło