Forståelse af Android Core: Looper, Handler og HandlerThread

forståelse af Android Core: Looper, Handler og HandlerThread

denne artikel dækker Android Looper, Handler og HandlerThread. Disse er blandt byggestenene i Android OS.

i min egen erfaring har jeg brugt dem i en meget begrænset sammenhæng indtil for nylig. Min brugssag involverede at sende opgaver til hoved – /ui-tråden, primært for at opdatere brugergrænsefladen fra enhver anden tråd. De andre aspekter af multi-threaded operationen blev håndteret gennem alternative måder som Threadpooleksekutor, IntentService og AsyncTask.

MultiThreading og opgavekørsel er gamle emner. Java selv har java.util.samtidig pakke og gaffel / slutte rammer for at lette det. Flere biblioteker er skrevet for at strømline asynkrone operationer. Rkjava er det mest populære bibliotek i dag til reaktiv programmering og design af en asynkron applikation.

så hvorfor skriver jeg om den gamle skole?

Looper, Handler, og HandlerThread er Android ‘ s måde at løse problemerne med asynkron programmering på. De er ikke old school, men en pæn struktur, som en kompleks android-ramme er bygget på.

for nye udviklere anbefales det stærkt at forstå principperne bag dem, og erfarne bør gennemgå dette emne for at huske de mindre detaljer.

jeg har også lavet en video tutorial til dette emne, og jeg kan varmt anbefale at se det. Klik her for at se nu.

Use Cases:

  1. hovedtråden i Android er bygget med en Looperog Handlers. Så forståelsen af det er vigtigt at oprette et ikke-blokeret responsivt brugergrænseflade.
  2. udviklerne, der skriver biblioteker, har ikke råd til at bruge tredjepartsbiblioteker på grund af bibliotekets størrelse. Så for dem er den bedste mulighed at udnytte den eksisterende tilgængelige ressource. At skrive egen løsning til det får måske ikke altid det niveau af effektivitet og optimering.
  3. det samme argument kan også fremsættes for virksomheder/enkeltpersoner, der sender SDK ‘ er ud. Klienterne kan have forskellige implementeringer, men alle af dem vil dele de fælles Android ramme API ‘ er.
  4. at forstå dem fuldt ud vil forbedre kapaciteten til at følge Android SDK og pakke klasser generelt.

lad os starte udforskningen/revisionen med et spørgeskema.

jeg forventer, at læseren har den grundlæggende forståelse af java-tråde. Hvis du har brug for det, så få et hurtigt overblik over java Thread og Runnable.

hvad er problemet med java-tråd?

Java-tråde er kun engangsbrug og dør efter udførelse af dens køremetode.

kan vi forbedre det?

tråden er et tveægget sværd. Vi kan fremskynde udførelsen ved at distribuere opgaverne mellem udførelsestråde, men kan også bremse den, når trådene er overskydende. Tråd skabelse i sig selv er en overhead. Så den bedste mulighed er at have et optimalt antal tråde og genbruge dem til udførelse af opgaver.

Model for tråd genanvendelighed:

  1. tråden holdes i live, i en løkke via det er run() metode.
  2. opgaven udføres serielt af denne tråd og vedligeholdes i en kø (Messagekø).
  3. tråden skal afsluttes, når den er færdig.

Hvad er Android ‘ s måde at gøre det på?

ovenstående model er implementeret i Android via Looper, Handlerog HandlerThread. Systemet kan visualiseres til at være et køretøj som i artiklens omslag.

  1. MessageQueue er en kø, der har opgaver kaldet meddelelser, som skal behandles.
  2. Handler spørger opgaven i MessageQueue ved hjælp af Looper og udfører dem også, når opgaven kommer ud af MessageQueue.
  3. Looper er en arbejdstager, der holder en tråd i live, løber igennem MessageQueue og sender meddelelser til den tilsvarende handler for at behandle.
  4. endelig Thread bliver afsluttet ved at kalde Looper ‘ s quit() metode.

en tråd kan kun have en unik Looper og kan have mange unikke handlere forbundet med det.

oprettelse Looper og Messagekø for en tråd:

en tråd får en Looper og MessageQueue ved at kalde Looper.prepare() efter dens kørsel. Looper.prepare() identificerer den kaldende tråd, opretter et Looper og MessageQueue objekt og knytter thread til dem i ThreadLocal lagringsklasse. Looper.loop() skal kaldes for at starte den tilknyttede looper. Tilsvarende skal looper afsluttes eksplicit gennem 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(); } }

oprettelse af Handler til en tråd:

A Handler bliver implicit forbundet med tråden, der instantierer den via trådens Looper, men vi kan eksplicit binde den til en tråd ved at føre trådens looperi konstruktøren af Handler.

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

afsendelse af meddelelser til MessageQueue via Handler kan udføres af to tilstande:

  1. Message: det er en klasse, der definerer forskellige nyttige metoder til at håndtere meddelelsesdata. For at sende et objekt indstiller vi obj-variablen.
Message msg = new Message();msg.obj = "Ali send message";handler.sendMessage(msg);

detaljeret oversigt over Message klasse kan findes her: https://developer.android.com/reference/android/os/Message.html

Runnable: en runnable kan også bogføres i MessageQueue. Eks: udstationering og kørsel af en opgave i hovedtråden.

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

i ovenstående eksempel opretter vi en Handler og giver Looper tilknyttet hovedtråden. Dette forbinder denne handler med hovedtråden. Når vi sender Runnable, bliver den i kø i hovedtrådens MessageQueue og derefter udført i hovedtråden.

Handler er i stand til meddelelsesmanipulation på en lang række måder, som kan findes her: https://developer.android.com/reference/android/os/Handler.html

oprettelse af en egen tråd og levering af Lopper og MessageQueue er ikke den rigtige måde at håndtere problemet på. Så Android har leveret HandlerThread (underklasse af Thread) for at strømline processen. Internt gør det de samme ting, som vi har gjort, men på en robust måde. Så brug altid HandlerThread.

en af måderne til at oprette HandlerThread er at underklasse det, og det meste af tiden bruger du denne metode.

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

Bemærk: Vi har instantieret handleren, når onLooperPrepared() kaldes. Så det Handler kan knyttes til det Looper.

  1. Looper er kun forberedt efter Handlerthreads start() kaldes dvs.efter at tråden kører.
  2. A Handler kan knyttes til a HandlerThread, først efter at det er Looper er forberedt.

anden måde at oprette HandlerThread:

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

Bemærk: HandlerThread skal ringe myHandlerThread.quit() for at frigøre ressourcerne og stoppe udførelsen af tråden.

jeg vil foreslå at øve ovenstående koder, så du kan forstå deres små detaljer.

jeg har oprettet et eksempelprojekt til postkontorsimulering. Posthuset er bygget på Handlertråd og klienter kommunikerer ved hjælp af posthuset. En Simulator klasse skaber få klient Bots og delegere deres kommunikation til de vigtigsteaktivitet, som gør det i en levende foder.

linket til dette eksempel

jeg har også oprettet en videotutorial til dette emne, og jeg anbefaler stærkt at se det. Klik her for at se nu.

lad os også blive venner på kvidre, Linkedin, Github og Facebook.

læring er en rejse, lad os lære sammen!

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.