Alle som prøver Android-utviklingen, oppdager betydningen av samtidighet. Den eneste måten å opprette en responsiv app på, er å la UI-tråden være så ledig som mulig, slik at alt det harde arbeidet blir gjort asynkront av bakgrunns tråder.
På grunn av utformingen av Android, administrerer tråder med bare java.lang.Thread
og java.util.concurrent
pakker kan være veldig vanskelig. Ved å bruke low-level threading-pakker med Android betyr det at du trenger å bekymre deg for mye vanskelig synkronisering for å unngå raseforhold. Heldigvis gjorde folkene på Google det harde arbeidet og bygget noen gode verktøy for å gjøre jobben enklere: AsyncTask
, IntentService
, loader
, AsyncQueryHandler
og CursorLoader
er alle nyttige, så vel som HaMeR-klassene handler
, Budskap
, og kjørbart
. Det er mange flotte alternativer for deg å velge mellom, hver med sine fordeler og ulemper.
Det har blitt mye sagt om AsyncTask
objekt, og mange bruker det som en sølvkule løsning for samtidighet på Android. Det er ekstremt nyttig for korte operasjoner, enkel å implementere, og sannsynligvis den mest populære tilnærmingen til samtidighet på Android. Hvis du vil lære mer om AsyncTask
, sjekk ut de følgende Envato Tuts + innleggene.
derimot, AsyncTask
bør ikke være det eneste verktøyet på verktøybeltet ditt.
For langvarige operasjoner, for komplekse samtidighet problemer, eller for å oppnå mer effektivitet i noen situasjoner, bør du velge en annen løsning. Hvis du trenger mer fleksibilitet eller effektivitet enn AsyncTask
gir, du kan bruke HaMeR (handler
, Budskap
& kjørbart
) rammeverk.I denne veiledningen vil vi utforske HaMeR-rammeverket, en av de kraftigste samtidige modellene som er tilgjengelige på Android, og vi lærer når og hvordan du bruker den. I en oppfølgingstutorial vil jeg vise deg hvordan du kodes et program for å prøve ut noen muligheter for HaMeR.
Følgende avsnitt vil introdusere betydningen av bakgrunnstråder for Android-systemet. Hvis du er kjent med dette konseptet, er du velkommen til å hoppe over det og gå direkte til diskusjonen om HaMeR-rammen i seksjon 3.
Når en Android-applikasjon er startet, er den første tråden som fremkommer av prosessen, hovedtråden, også kjent som UI-tråden, som er ansvarlig for å håndtere alt brukergrensesnittlogikken. Dette er den viktigste tråden i et program. Det er ansvarlig for å håndtere all brukerinteraksjon og også "binde" programmets bevegelige deler sammen. Android tar dette veldig alvorlig, og hvis brukergrensesnittet ditt sitter fast, arbeider på en oppgave i mer enn noen sekunder, vil appen krasje.
[UI-tråden] er svært viktig fordi den har ansvaret for å sende hendelser til de riktige brukergrensesnittene, inkludert tegnearrangementer. Det er også tråden der applikasjonen din interagerer med komponenter fra Android UI toolkit (komponenter fraandroid.widget
ogandroid.view
pakker). Som sådan kalles også hovedtråden noen ganger UI-tråden. - Prosesser og tråder, Android Developer Guide
Problemet er at nesten all kode i en Android-applikasjon vil bli utført på UI-tråden som standard. Siden oppgavene på en tråd gjøres i rekkefølge, betyr dette at brukergrensesnittet kan "fryse", blir uforsvarlig mens det behandler noe annet arbeid.
Langtidsoppgaver som kreves på brukergrensesnittet, vil trolig være dødelig for appen din, og en ANR (Application Not Responding) dialog vises. Selv små oppgaver kan kompromittere brukeropplevelsen, og dermed er den riktige tilnærmingen å fjerne så mye arbeid som mulig fra brukergrensesnittet ved hjelp av bakgrunnstråder. Som sagt tidligere, er det mange måter å løse dette problemet på, og vi vil utforske HaMeR-rammeverket, en av kjerne-løsningene fra Android for å løse denne situasjonen.
HaMeR-rammen tillater bakgrunns tråder å sende meldinger eller post runnables til brukergrensesnittet og til alle andre tråder MessageQueue
via handlers. HaMeR refererer til handler
, Budskap
, & kjørbart
. Det er også noen andre viktige klasser som samarbeider med HaMeR: Looper
og MessageQueue
. Sammen er disse objektene ansvarlige for å lette trådstyring på Android, ta vare på synkronisering og gi enkle metoder for bakgrunnstråder for å kommunisere med brukergrensesnittet og med andre tråder.
Slik går det i klassene i HaMeR-rammen.
Looper
kjører en meldingssløyfe på en tråd ved hjelp av MessageQueue
.MessageQueue
inneholder en liste over meldinger som skal sendes av Looper
.handler
tillater sending og behandling av Budskap
og kjørbart
til MessageQueue
. Det kan brukes til å sende og behandle meldinger mellom tråder.Budskap
inneholder en beskrivelse og data som kan sendes til en handler.kjørbart
representerer en oppgave som skal utføres.Med HaMeR-rammen kan tråder sende meldinger eller legge ut runnable objekter enten til seg selv eller til brukergrensesnittet. HaMeR fremmer også bakgrunnsinteraksjoner via handler
.
handler
er HaMeR arbeidshorse. Det er ansvarlig for å sende Budskap
(data melding) og innlegg kjørbart
(oppgavemeddelelse) objekter til MessageQueue
assosiert med a Tråd
. Etter at oppgavene er levert til køen, mottar håndterer objektene fra Looper
og behandler meldingene ved riktig tidspunkt ved hjelp av handler
forbundet med det.
EN handler
kan brukes til å sende eller poste Budskap
og kjørbart
objekter mellom tråder, så lenge slike tråder deler samme prosess. Ellers vil det være nødvendig å opprette en interprosesskommunikasjon (IPC), en metode som overgår omfanget av denne opplæringen.
EN handler
må alltid være knyttet til a Looper
, og denne forbindelsen må gjøres i løpet av sin oppstart. Hvis du ikke gir en Looper
til handler
, det vil være bundet til dagens Tråd
's Looper
.
// Handler bruker nåværende trådens Looper Handler handler = ny Handler (); // Handler bruker Looper gir Handler handler = ny Handler (Looper);
Husk at a handler
er alltid knyttet til a Looper
, og denne forbindelsen er permanent og kan ikke endres når den er etablert. Imidlertid a Looper
tråden kan ha foreninger med flere handler
s. Det er også viktig å merke seg at a Looper
må være aktiv før foreningen med a handler
.
Samarbeidet mellom Looper
og MessageQueue
I en Java-tråd opprettes en løkke med oppgaver som behandles i rekkefølge. En slik løkke vil holde tråden i live mens den venter på å motta flere oppgaver. En tråd kan bare ha en Looper
og en MessageQueue
forbundet med det; Det kan imidlertid være flere håndtere for hver tråd. Handlers er ansvarlige for å behandle oppgavene i køen, og hver oppgave vet hvilken handler som er ansvarlig for behandlingen.
Brukergrensesnittet eller hovedtråden er den eneste typen tråd som som standard allerede har a handler
, en Looper
, og a MessageQueue
. Andre tråder må være forberedt med disse objektene før de kan arbeide med HaMeR-rammen. Først må vi opprette en Looper
som allerede inneholder a MessageQueue
og fest den til tråden. Du kan gjøre dette med en underklasse av Tråd
, som følger.
// Forbereder en tråd for HaMeR-klassen LooperThread utvider tråden public Handler mHandler; offentlig tomgangsløp () // legge til og klargjøre Looper Looper.prepare (); // Handler-forekomsten vil bli knyttet til Thread's Looper mHandler = ny Handler () Offentlig tomgangshåndteringMessage (Message msg) // behandle innkommende meldinger her; // Starte meldingen kø loop med Looper Looper.loop ();
Det er imidlertid enklere å bruke en hjelpeklasse som heter HandlerThread
, som har a Looper
og a MessageQueue
innebygd i en Java Tråd
og er klar til å motta en Handler.
// HandlerThread-klassen inneholder en fungerende Looper-offentlig klasse HamerThread utvider HandlerThread // du trenger bare å legge til Handler Private Handler Handler; offentlig HamerThread (String navn) super (navn);
De kjørbart
er et Java-grensesnitt som har mange bruksområder. Det kan forstås som en enkelt oppgave som skal utføres på en Tråd
. Den har en enkelt metode som må implementeres, Runnable.run ()
, å utføre oppgaven.
// Deklarere en Runnable Runnable r = Ny Runnable () @Override offentlig tomgang () // oppgaven går her;
Det er flere alternativer å legge inn en kjørbart
på en handler
.
Handler.post (Runnable r)
: Legg til kjørbart
til MessageQueue
.Handler.postAtFrontOfQueue (Runnable r)
: Legg til kjørbart
på forsiden av MessageQueue
.handler.postAtTime (Runnable r, long timeMillis)
: Legg til kjørbart
på MessageQueue
å bli kalt på et bestemt tidspunkt.handler.postDelayed (Runnable r, lang forsinkelse)
: Legg til kjørbart
til køen som skal ringes etter at en bestemt tid har gått.// Posting a Runnable på en Handler Handler Handler = Ny Handler (); handler.post (new Runnable () @Override public void run () // oppgaven går her);
Det er også mulig å bruke standardbrukerens brukerhåndterer til å legge inn en kjørbart
ringer Activity.runOnUiThread ()
.
// posting Runnable ved hjelp av UI Handler Activity.runOnUiThread (ny Runnable () @Override public void run () // oppgave å utføre);
Det er viktig å huske på noen ting om kjørbart
s. I motsetning til en Budskap
, en kjørbart
kan ikke resirkuleres - når jobben er ferdig, er den død. Siden det er en del av en standard Java-pakke, a kjørbart
er ikke avhengig av handler
og kan kalles på en standard Tråd
bruker Runnable.run ()
metode. Denne tilnærmingen har imidlertid ikke noe å gjøre med HaMeR-rammeverket, og vil ikke dele noen av fordelene.
De Budskap
objekt definerer en melding som inneholder en beskrivelse og noen vilkårlig data som kan sendes og behandles via handler
. De Budskap
er identifisert med en int
definert på Message.what ()
. De Budskap
kan holde to andre int
argumenter og an Gjenstand
å lagre ulike typer data.
Message.what
: int
identifisere Budskap
Message.arg1
: int
vilkårlig argumentasjonMessage.arg2
: int
vilkårlig argumentasjonMessage.obj
: Gjenstand
å lagre ulike typer data Når du trenger å sende en melding, i stedet for å lage en fra begynnelsen, er den anbefalte tilnærmingen å hente en resirkulert direkte fra det globale bassenget med Message.obtain ()
eller Handler.obtainMessage ()
kommandoer. Det finnes noen forskjellige versjoner av de metodene som lar deg få en Budskap
i henhold til ditt behov.
En vanlig bruk av Handler.obtainMessage ()
er når du trenger å sende en melding til en bakgrunnstråd. Du vil bruke handler
forbundet med den tråden er Looper
å få en Budskap
og send den til bakgrunns tråden, som i eksemplet nedenfor.
int hva = 0; String hallo = "Hei!"; // Hent melding knyttet til bakgrunnen Trådmelding msg = handlerBGThread.obtainMessage (hva, hallo); // Sende meldingen til bakgrunnen Thread handlerBGThread.sendMessage (msg);
Det er mange kule metoder på Budskap
klasse, og jeg anbefaler deg å ta en nærmere titt på dokumentasjonen.
sende melding()
alternativerPå samme måte som hvordan vi kan legge inn kjørbart
s, det er flere alternativer å sende Budskap
s:
Handler.sendMessage (Meldingsmelding)
: Legg til en Budskap
til MessageQueue
.Handler.sendMessageAtFrontOfQueue (Meldingsmelding)
: Legg til en Budskap
til forsiden av MessageQueue
.Handler.sendMessageAtTime (Message msg, long timeInMillis)
: Legg til en Budskap
til køen på et bestemt tidspunkt.Handler.sendMessageDelayed (Message msg, long timeInMillis)
: Legg til en Budskap
til køen etter at en bestemt tid har gått.De Budskap
objekter sendt av Looper
behandles av handleren med metoden Handler.handleMessage
. Alt du trenger å gjøre er å forlenge handler
klassen og overstyr denne metoden for å behandle meldingene.
offentlig klasse MessageHandler utvider Handler @Override public void handleMessage (Melding msg) switch (msg.what) // håndtere 'Hello' msg tilfelle 0: String hallo = (String) msg.obj; System.out.println (hei); gå i stykker;
HaMeR-rammeverket kan bidra til å forbedre Android-programmets samtidige kode. Det kan virke forvirrende først når det sammenlignes med enkelheten til en AsyncTask
, men haMeRs åpenhet kan være en fordel hvis den brukes riktig.
Huske:
Handler.post ()
metoder brukes når avsendere vet hvilke operasjoner som skal utføres.Handler.sendMessage()
metoder brukes når mottakeren vet hvilken operasjon som skal utføres.Hvis du vil vite mer om tråder i Android, kan du være interessert i boken Efficient Android Threading: Asynkron Behandlingsteknikker for Android Applications av Anders Goransson.
I den neste opplæringen fortsetter vi å utforske HaMeR-rammeverket med en praktisk tilnærming, ved å bygge et program som demonstrerer forskjellige måter å bruke denne Android-konseptrammen på. Vi lager denne appen fra bakken, prøver forskjellige muligheter som kommunikasjon mellom tråder
, snakker med brukergrensesnittet, samt sende meldinger og innlegg kjørbart
s med forsinkelser.
Ser deg snart!