Android-ytimen ymmärtäminen: Looper, Handler ja HandlerThread

Understanding Android Core: Looper, Handler, and HandlerThread

tämä artikkeli kattaa Android Looper, Handler ja HandlerThread. Nämä ovat muun muassa Android-käyttöjärjestelmän rakennuspalikoita.

oman kokemukseni mukaan olen käyttänyt niitä hyvin rajoitetusti viime aikoihin asti. Oma käyttötapaus mukana lähettämällä tehtäviä main / ui säiettä, ensisijaisesti päivittää UI mistä tahansa muusta säiettä. Muut näkökohdat monisäikeinen toiminta käsiteltiin vaihtoehtoisilla tavoilla, kuten ThreadPoolExecutor, IntentService, ja AsyncTask.

monilukutaito ja tehtäväjuoksu ovat vanhoja oppiaineita. Jaavalla itsessään on java.util.samanaikainen paketti ja haarukka / liittyä puitteet helpottaa sitä. Asynkronisen toiminnan virtaviivaistamiseksi on kirjoitettu useita kirjastoja. RxJava on nykyään suosituin kirjasto reaktiiviseen ohjelmointiin ja asynkronisen sovelluksen suunnitteluun.

niin, miksi kirjoitan vanhasta koulukunnasta?

Looper, Handler, ja HandlerThread ovat Androidin tapa ratkaista asynkronisen ohjelmoinnin ongelmia. Ne eivät ole vanhaa koulukuntaa, vaan siisti rakenne, jolle monimutkainen android-kehys on rakennettu.

uusille kehittäjille on erittäin suositeltavaa ymmärtää niiden taustalla olevat periaatteet ja kokeneiden tulisi palata tähän aiheeseen muistellakseen pieniä yksityiskohtia.

olen luonut aiheesta myös opetusvideon, jota suosittelen lämpimästi katsomaan. Klikkaa tästä katsella nyt.

Käyttötapaukset:

  1. Androidin pääkierre on rakennettu Looper ja Handlers. Niin, ymmärtäminen on tärkeää luoda estämätön reagoiva UI.
  2. kirjastoja kirjoittavilla kehittäjillä ei ole varaa käyttää kolmannen osapuolen kirjastoja kirjaston koon vuoksi. Niin, heille, paras vaihtoehto on hyödyntää olemassa olevia resursseja. Kirjoittaminen oma ratkaisu se ei välttämättä aina saada, että tehokkuuden ja optimointi.
  3. sama väite voidaan esittää myös SDK: ta toimittaville yrityksille / yksityishenkilöille. Asiakkailla voi olla erilaisia toteutuksia, mutta kaikki jakavat yhteiset android framework-sovellusliittymät.
  4. niiden täysi ymmärtäminen parantaa kykyä seurata Androidin SDK-ja pakettiluokkia ylipäätään.

aloitetaan etsintä / tarkistus kyselyllä.

odotan lukijalta java-kierteiden peruskäsitystä. Jos tarvitset, niin saat nopean yleiskuvan java säiettä ja ajettavissa.

mikä on java-langan ongelma?

Java-kierteet ovat vain kertakäyttöisiä ja kuolevat suoritustapansa suorittamisen jälkeen.

Voimmeko parantaa sitä?

lanka on kaksiteräinen miekka. Voimme nopeuttaa suoritusta jakamalla tehtävät suorittamisen kierteiden kesken, mutta voimme myös hidastaa sitä, kun kierteitä on liikaa. Langanluonti itsessään on ylimenevää. Niin, paras vaihtoehto on olla optimaalinen määrä säikeitä ja käyttää niitä tehtävien suorittamiseen.

langan uudelleenkäytettävyyden malli:

  1. Lanka pidetään elossa, silmukassa sen run() – menetelmän kautta.
  2. tehtävä suoritetaan sarjallisesti kyseisen säikeen avulla ja pidetään jonossa (MessageQueue).
  3. säie on lopetettava, kun se on tehty.

mikä on Androidin tapa tehdä se?

edellä mainittu malli on toteutettu Androidin kautta Looper, Handler ja HandlerThread. Järjestelmä voidaan visualisoida ajoneuvoksi kuten artikkelin kannessa.

  1. MessageQueue on jono, jonka tehtäviä kutsutaan viesteiksi, jotka pitäisi käsitellä.
  2. Handler tiedustelee tehtävää MessageQueue käyttäen Looper ja suorittaa ne myös tehtävän tullessa ulos MessageQueue: stä.
  3. Looper on työntekijä, joka pitää langan elossa, silmukoi MessageQueue läpi ja lähettää viestejä vastaavalle handler prosessoitavaksi.
  4. lopulta Thread lopetetaan kutsumalla Looper quit() – menetelmää.

yhdellä langalla voi olla vain yksi uniikki Looper ja siihen voi liittyä monia uniikkeja käsittelijöitä.

Looper ja MessageQueue langalle:

Lanka saa Looper ja MessageQueue soittamalla Looper.prepare() juoksunsa jälkeen. Looper.prepare() tunnistaa kutsuvan langan, luo Looper ja MessageQueue objektin ja liittää thread niihin ThreadLocal tallennusluokan. Looper.loop()on kutsuttava käynnistämään siihen liittyvä looper. Vastaavasti looper on päätyttävä eksplisiittisesti looper.quit()kautta.

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

Lankakäsittelijän luominen:

a Handler liittyy implisiittisesti lankaan, joka instantioi sen langan Looper kautta, mutta voimme eksplisiittisesti sitoa sen lankaan ohittamalla langan looper Handlerrakentajan.

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

viestien lähettäminen MessageQueue kautta Handler voidaan tehdä kahdella tavalla:

  1. Message: se on luokka, joka määrittelee erilaisia hyödyllisiä menetelmiä käsitellä viestitietoja. Lähettääksemme objektin asetamme obj-muuttujan.
Message msg = new Message();msg.obj = "Ali send message";handler.sendMessage(msg);

yksityiskohtainen katsaus Message luokkaan löytyy täältä: https://developer.android.com/reference/android/os/Message.html

Runnable: myös MessageQueuevoi lähettää runneltavan. Esim: tehtävän lähettäminen ja suorittaminen pääkierteessä.

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

yllä olevassa esimerkissä luodaan Handler ja annetaan Looper liittyy pääkierteeseen. Tämä liittää tämän käsittelijän pääkierteeseen. Kun postaamme Runnable, se jonoutuu pääkierteeseen MessageQueue ja suoritetaan sitten pääkierteeseen.

Handler kykenee viestimanipulaatioon hyvin monella eri tavalla, mikä löytyy täältä: https://developer.android.com/reference/android/os/Handler.html

Oman kierteen luominen ja Lopper ja MessageQueue tarjoaminen ei ole oikea tapa käsitellä ongelmaa. Niin, Android on tarjonnut HandlerThread(alaluokka Thread) virtaviivaistaa prosessia. Sisäisesti se tekee samoja asioita kuin me olemme tehneet, mutta jämäkästi. Käytä siis aina HandlerThread.

yksi tapa luoda Käsittelijäluku on sen alaluokka ja useimmiten käytät tätä menetelmää.

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

Huom: olemme instantioineet käsittelijän, kun onLooperPrepared() kutsutaan. Niin, että Handler voidaan liittää siihen Looper.

  1. Looper valmistetaan vasta kun Handlerthreadin start() kutsutaan eli kun lanka on käynnissä.
  2. a Handler voidaan liittää HandlerThread: iin vasta sen jälkeen, kun Looper on valmistettu.

muu tapa luoda Käsittelyleima:

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

Huomautus: Handlerthreadin on soitettava myHandlerThread.quit() vapauttaakseen resurssit ja pysäyttääkseen langan suorittamisen.

Kehottaisin harjoittelemaan edellä mainittuja koodeja, jotta niiden pienet yksityiskohdat selviäisivät.

olen luonut Esimerkkiprojektin Postin simulointiin. Posti rakentuu Käsittelyleiman varaan ja asiakkaat kommunikoivat postin avulla. Simulaattoriluokka luo harvoja Asiakasbotteja ja delegoi viestintänsä Pääaktiivisuudelle, joka tekee siitä live-syötteen.

linkki tähän esimerkkiin

olen luonut aiheesta myös opetusvideon, jota suosittelen lämpimästi katsomaan. Klikkaa tästä katsella nyt.

ystävystytään myös Twitterissä, LinkedInissä, GitHubissa ja Facebookissa.

oppiminen on matka, opitaan yhdessä!

Vastaa

Sähköpostiosoitettasi ei julkaista.