Înțelegerea Android Core: Looper, Handler și HandlerThread

înțelegerea Android Core: Looper, Handler și HandlerThread

acest articol se referă la Android Looper, Handler și HandlerThread. Acestea sunt printre blocurile de construcție ale sistemului de operare Android.

în propria mea experiență, le-am folosit într-un context foarte limitat până de curând. Cazul meu de utilizare a implicat trimiterea sarcinilor la firul principal / ui, în primul rând pentru a actualiza interfața de utilizare din orice alt fir. Celelalte aspecte ale operațiunii multi-threaded au fost tratate prin moduri alternative, cum ar fi ThreadPoolExecutor, IntentService, și AsyncTask.

MultiThreading și task running sunt subiecte vechi. Java în sine are java.util.pachet concurente și furculiță / se alăture cadru pentru a facilita. Mai multe biblioteci au fost scrise pentru a eficientiza operațiunile asincrone. RxJava este cea mai populară bibliotecă de astăzi pentru programarea reactivă și proiectarea unei aplicații asincrone.

deci, de ce scriu despre vechea școală?

Looper, Handler, și HandlerThread sunt modul Android de a rezolva problemele programării asincrone. Nu sunt școală veche, ci o structură îngrijită pe care este construit un cadru android complex.

pentru dezvoltatorii noi, este foarte recomandat să înțeleagă principiile din spatele lor și cu experiență unul ar trebui să revizuiască acest subiect pentru a aminti detaliile minore.

am creat și un tutorial video pentru acest subiect și vă recomand să îl urmăriți. Click aici pentru a viziona acum.

Cazuri De Utilizare:

  1. firul principal din Android este construit cu un Looper și Handlers. Deci, înțelegerea este esențială pentru a crea un UI receptiv deblocat.
  2. dezvoltatorii care scriu biblioteci nu își pot permite să utilizeze biblioteci terțe din cauza dimensiunii bibliotecii. Deci, pentru ei, cea mai bună opțiune este utilizarea resurselor disponibile existente. Scrierea soluției proprii pentru aceasta nu poate obține întotdeauna acel nivel de eficiență și optimizare.
  3. același argument poate fi făcut și pentru companiile/persoanele fizice care expediază SDK-uri. Clienții pot avea implementări variate, dar toți vor împărtăși API-urile comune Android framework.
  4. înțelegerea lor pe deplin va spori capacitatea de a urma SDK-ul Android și clasele de pachete în general.

să începem explorarea/revizuirea cu un chestionar.

mă aștept ca cititorul să aibă înțelegerea de bază a firelor java. Dacă aveți nevoie, obțineți o privire de ansamblu rapidă asupra java Thread și Runnable.

care este problema cu java thread?

firele Java sunt doar o singură utilizare și mor după executarea metodei sale de rulare.

îl putem îmbunătăți?

firul este o sabie cu două tăișuri. Putem accelera execuția prin distribuirea sarcinilor între firele de execuție, dar o putem încetini și atunci când firele sunt în exces. Crearea firului în sine este o deasupra capului. Deci, cea mai bună opțiune este să aveți un număr optim de fire și să le reutilizați pentru executarea sarcinilor.

Model pentru reutilizarea firului:

  1. firul este ținut în viață, într-o buclă prin metoda run().
  2. sarcina este executată în serie de acel fir și este menținută într-o coadă (MessageQueue).
  3. firul trebuie terminat când ați terminat.

care este modul Android de a face acest lucru?

modelul de mai sus este implementat în Android prin Looper, Handlerși HandlerThread. Sistemul poate fi vizualizat ca un vehicul ca în coperta articolului.

  1. MessageQueue este o coadă care are sarcini numite mesaje care ar trebui procesate.
  2. Handler enqueues sarcina în MessageQueue folosind Looper și, de asemenea, le execută atunci când sarcina iese din MessageQueue.
  3. Looper este un lucrător care ține un fir în viață, bucle prin MessageQueue și trimite mesaje la handler corespunzător pentru a procesa.
  4. în cele din urmă Thread se termină apelând metoda quit() a lui Looper.

un fir poate avea un singur Looper unic și poate avea multe Handlere unice asociate cu acesta.

crearea Looper și MessageQueue pentru un fir:

un fir devine un Looper și MessageQueue apelând Looper.prepare() după rularea acestuia. Looper.prepare() identifică firul de apelare, creează un obiect Looper și MessageQueue și asociază thread cu ele în clasa de stocare ThreadLocal. Looper.loop() trebuie apelat pentru a porni looper-ul asociat. În mod similar, looper trebuie reziliat în mod explicit prin 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(); } }

crearea Handler-ului pentru un fir:

un Handler devine implicit asociat cu firul care îl instanțiază prin firul Looper, dar îl putem lega în mod explicit de un fir trecând firul looper în constructorul Handler.

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

trimiterea mesajelor către MessageQueue prin Handler se poate face prin două moduri:

  1. Message: este o clasă care definește diferite metode utile pentru a face față datelor mesajelor. Pentru a trimite un obiect, setăm variabila obj.

Message msg = new Message();msg.obj = "Ali send message";handler.sendMessage(msg);

prezentare detaliată a clasei Message poate fi găsită aici: https://developer.android.com/reference/android/os/Message.html

Runnable: un runnable poate fi, de asemenea, postat în MessageQueue. Ex: postarea și rularea unei sarcini în firul principal.

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

în exemplul de mai sus, vom crea un Handler și să furnizeze Looper asociate cu firul principal. Acest lucru asociază acest handler la firul principal. Când postăm Runnable, acesta se află în coada de așteptare în firul principal MessageQueue și apoi executat în firul principal.

Handler este capabil de manipulare mesaj într-o mare varietate de moduri, care pot găsite aici: https://developer.android.com/reference/android/os/Handler.html

crearea unui fir propriu și furnizarea Lopper și MessageQueue nu este modalitatea corectă de a rezolva problema. Deci, Android a furnizat HandlerThread(subclasa Thread) pentru a eficientiza procesul. Pe plan intern face aceleași lucruri pe care le-am făcut, dar într-un mod robust. Deci, utilizați întotdeauna HandlerThread.

una dintre modalitățile de a crea HandlerThread este să o subclasați și de cele mai multe ori veți folosi această metodă.

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 } }; }}

Notă: Am instanțiat Handler atunci când onLooperPrepared() este numit. Deci, acel Handler poate fi asociat cu acel Looper.

  1. Looper este pregătit numai după HandlerThread ‘ s start() se numește adică după ce firul rulează.
  2. un Handler poate fi asociat cu un HandlerThread, numai după ce este pregătit Looper.

alt mod de a crea HandlerThread:

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

notă: HandlerThread trebuie să apeleze myHandlerThread.quit() pentru a elibera resursele și a opri executarea firului.

aș sugera practicarea codurilor de mai sus, astfel încât să puteți înțelege micile lor detalii.

am creat un exemplu de proiect pentru simularea Oficiului Poștal. Oficiul Poștal este construit pe Handlerfir și clienții comunică cu ajutorul Oficiului Poștal. O clasă de Simulator creează puțini roboți clienți și delegă comunicarea lor Principaluluiactivitate, care o face într-un feed live.

link-ul de la acest exemplu

am creat, de asemenea, un tutorial video pentru acest subiect, și am foarte recomanda sa ma uit la ea. Click aici pentru a viziona acum.

de asemenea, să devenim prieteni pe Twitter, Linkedin, Github și Facebook.

învățarea este o călătorie, să învățăm împreună!

Lasă un răspuns

Adresa ta de email nu va fi publicată.