Porozumění Android Core: Looper, Handler, a HandlerThread

Porozumění Android Core: Looper, Handler, a HandlerThread

Tento Článek pokrývá Android Looper, Handler, a HandlerThread. Ty patří mezi stavební kameny OS Android.

z vlastní zkušenosti jsem je až donedávna používal ve velmi omezeném kontextu. Můj případ použití zahrnoval odesílání úkolů do hlavního vlákna / ui, především k aktualizaci uživatelského rozhraní z jakéhokoli jiného vlákna. Ostatní aspekty vícevláknové operace byly řešeny alternativními způsoby, jako je ThreadPoolExecutor, IntentService a AsyncTask.

MultiThreading a běh úloh jsou staré předměty. Samotná Java má Javu.util.souběžné balíček a vidlice / Join rámec pro usnadnění. Pro zefektivnění asynchronních operací bylo napsáno několik knihoven. RxJava je dnes nejoblíbenější knihovnou pro reaktivní programování a navrhování asynchronní aplikace.

proč tedy píšu o staré škole?

Looper, Handler, a HandlerThread jsou Android způsob řešení problémů asynchronního programování. Nejedná se o starou školu, ale o úhlednou strukturu, na které je postaven komplexní rámec android.

pro nové vývojáře je vysoce doporučeno porozumět principům, které za nimi stojí, a zkušení by se měli k tomuto tématu vrátit, aby si vzpomněli na drobné detaily.

také jsem vytvořil video tutoriál pro toto téma a vřele doporučuji sledovat ho. Klikněte sem a sledujte nyní.

Případy Použití:

  1. hlavní vlákno v Androidu je postaveno s Looper a Handlers. Takže pochopení je nezbytné vytvořit odblokované citlivé uživatelské rozhraní.
  2. vývojáři píšící knihovny si nemohou dovolit používat knihovny třetích stran kvůli velikosti knihovny. Takže pro ně je nejlepší možností využít stávající dostupný zdroj. Psaní vlastního řešení pro něj nemusí vždy získat takovou úroveň efektivity a optimalizace.
  3. stejný argument lze také učinit pro společnosti / jednotlivce, kteří odesílají sady SDK. Klienti mohou mít různé implementace, ale všichni budou sdílet společné API rozhraní Android framework.
  4. jejich úplné pochopení zvýší schopnost sledovat třídy Android SDK a balíček obecně.

začněme průzkum/revizi dotazníkem.

očekávám, že čtenář bude mít základní znalosti o vláknech java. Pokud potřebujete, získáte rychlý přehled o vlákně java a spustitelném.

jaký je problém s vláknem java?

vlákna Java jsou pouze jednorázová a po provedení metody běhu zemřou.

můžeme to zlepšit?

vlákno je dvousečný meč. Můžeme urychlit provádění distribucí úkolů mezi podprocesy provádění, ale můžeme je také zpomalit, když jsou vlákna v přebytku. Vytvoření vlákna samo o sobě je režie. Nejlepší možností je tedy mít optimální počet vláken a znovu je použít pro provádění úkolů.

Model pro opětovné použití závitu:

  1. vlákno je udržováno naživu, ve smyčce pomocí metody run().
  2. úloha je prováděna sériově tímto vláknem a je udržována ve frontě (MessageQueue).
  3. podproces musí být po dokončení ukončen.

jaký je způsob Androidu?

výše uvedený model je implementován v systému Android prostřednictvím Looper, Handler a HandlerThread. Systém lze vizualizovat jako vozidlo jako v obálce článku.

  1. MessageQueue je fronta, která má úkoly zvané zprávy, které by měly být zpracovány.
  2. Handler zadá úkol v MessageQueue pomocí Looper a také je provede, když úkol vyjde z MessageQueue.
  3. Looper je pracovník, který udržuje vlákno naživu, smyčky přes MessageQueue a odešle zprávy odpovídajícímu handler ke zpracování.
  4. nakonec Thread ukončí voláním Looperovy metody quit().

jedno vlákno může mít pouze jeden jedinečný Looper a může s ním být spojeno mnoho jedinečných manipulátorů.

Vytvoření Looper a MessageQueue pro Vlákno:

vlákno dostane Looper a MessageQueue zavoláním Looper.prepare() po jeho spuštění. Looper.prepare() identifikuje volající vlákno, vytvoří objekt Looper a MessageQueue a přidruží k nim thread ve třídě úložiště ThreadLocal. Looper.loop()musí být voláno pro spuštění přidruženého looperu. Podobně musí být looper explicitně ukončeno pomocí looper.quit().

class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here // this will run in non-ui/background thread } }; Looper.loop(); } }

Vytvořit Handler pro Vlákno:

Handler dostane implicitně spojené s podproces, který vytvoří instanci ji pomocí závitu Looper, ale můžeme explicitně svázat je se závitem kolem závitu je looper v konstruktoru Handler.

handler = new Handler() {@Overridepublic void handleMessage(Message msg) { // process incoming messages here // this will run in the thread, which instantiates it }};

odesílání zpráv na MessageQueue přes Handler lze provést dvěma režimy:

  1. Message: je to třída, která definuje různé užitečné metody pro řešení dat zpráv. Pro odeslání objektu nastavíme proměnnou obj.
Message msg = new Message();msg.obj = "Ali send message";handler.sendMessage(msg);

Podrobný přehled Message třídy lze nalézt zde: https://developer.android.com/reference/android/os/Message.html

Runnable: runnable, může být také zveřejněny v MessageQueue. Příklad: odeslání a spuštění úlohy v hlavním vlákně.

new Handler(Looper.getMainLooper()).post(new Runnable() {@Overridepublic void run() { // this will run in the main thread }});

ve výše uvedeném příkladu vytvoříme Handler a poskytneme Looper přidružené k hlavnímu vláknu. Toto přidruží tuto obslužnou rutinu k hlavnímu vláknu. Když zveřejníme Runnable, dostane se do fronty v hlavním vlákně MessageQueue a poté se spustí v hlavním vlákně.

Handler je schopen zprávu manipulaci v široké škále způsobů, které můžete nalézt zde: https://developer.android.com/reference/android/os/Handler.html

Vytvoření vlastní vlákno a poskytuje Lopper a MessageQueue není správný způsob, jak se vypořádat s problémem. Android tedy poskytl HandlerThread(podtřída Thread) pro zefektivnění procesu. Vnitřně dělá to samé, co jsme udělali, ale robustním způsobem. Takže vždy používejte HandlerThread.

jedním ze způsobů, jak vytvořit HandlerThread, je podtřída a většinu času budete používat tuto metodu.

private class MyHandlerThread extends HandlerThread { Handler handler; public MyHandlerThread(String name) { super(name); } @Override protected void onLooperPrepared() { handler = new Handler(getLooper()) { @Override public void handleMessage(Message msg) { // process incoming messages here // this will run in non-ui/background thread } }; }}

Poznámka: Při volání onLooperPrepared() jsme vytvořili instanci handleru. Takže, že Handler může být spojeno s tím Looper.

  1. Looper je připraven pouze po HandlerThread je start() se nazývá tj. po spuštění vlákna.
  2. a Handler může být spojeno s HandlerThread, až poté, co je připraveno Looper.

jiný způsob, jak vytvořit HandlerThread:

HandlerThread handlerThread = new HandlerThread("MyHandlerThread");handlerThread.start();Handler handler = new Handler(handlerThread.getLooper());

Poznámka: HandlerThread musí zavolat myHandlerThread.quit(), aby uvolnil zdroje a zastavil provádění podprocesu.

navrhoval bych cvičit výše uvedené kódy, takže můžete pochopit jejich malé detaily.

vytvořil jsem ukázkový projekt pro simulaci pošty. Pošta je postavena na HandlerThread a klienti komunikují s pomocí pošty. Třída simulátoru vytváří několik klientských robotů a deleguje jejich komunikaci na MainActivity, což ji činí v živém přenosu.

odkaz na tento příklad

také jsem vytvořil video tutoriál pro toto téma a vřele doporučuji sledovat jej. Klikněte sem a sledujte nyní.

také se staňte přáteli na Twitteru,Linkedin, Github a Facebook.

učení je cesta, Učme se společně!

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.