Android AsyncTask atferd endrer du bør vite

Google vil at du skal elske Android AsyncTask-mønsteret. Jeg innrømmer at jeg, fra en innebygd C / C ++ bakgrunn, var litt skeptisk til å overlevere den langvarige I / O-en til en svartbokset trådbasseng. Men med tiden satte jeg pris på klassen og dens enkelhet. Det fungerte bra, og jeg trengte ikke lure med det.

Men den siste uken fikk jeg uventet oppførsel. En bruker rapporterte veldig treg I / O på en av applikasjonene mine etter at han oppgraderte fra en eldre enhet til en nyere. Dette var motsatt av hva man kunne forvente, så jeg kastet raskt sammen en rudimentær test for å trekke noen beregninger.

Tenk på følgende kodebit:

 for ( int i = 0; i <5; i ++) { 
 AsyncTask1 oppgave = new AsyncTask1 (); 
 task.execute (); 
 } 

Selv uten å vite hva som skjer i AysncTask1-implementeringen, er tankene mine, etter mitt sinn, å starte fem av disse oppgavene. Så for testen min simulerte jeg litt langvarig I / O ved å overstyre doInBackground-funksjonen til AsyncTask1 til å sove i 1000 millisekunder.

 @Overstyring 
 beskyttet objekt doInBackground (Object ... arg0) prøve { 
 Tråd. søvn ( ONE_SECOND ); 
 } fangst (InterruptException e) {// TODO Auto-generert fangstblokk 
 e.printStackTrace (); 
 } 
 return null ; 
 } 
Etter å ha satt inn noen grunnleggende feilsøkingstimer, kjørte jeg koden i to AVD-forekomster: en som kjører Eclair (Android 2.0) og en som kjører Jelly Bean (Android 4.2). Resultatene overrasket meg. Ta en titt selv ( figur A ). Figur A

Det er riktig - Android 2.0 forlot den nyeste og beste versjonen av operativsystemet og spiste støv. Du trenger ikke å være så skarp for å multiplisere forsinkelsen på ett sekund vi hardkodet inn i vår AsyncTask med de fem iterasjonene av vår for-loop for å gjette hva som skjer: Android kjører oppgavene serielt i stedet for parallelt. Jeg begynte å pirke rundt på forumene og ble etter hvert rettet tilbake til Googles AsyncTask-dokumentasjon. Omtrent en tredjedel av veien nedover på siden finner du følgende merknad:

"Fra HONEYCOMB utføres oppgaver på en enkelt tråd for å unngå vanlige applikasjonsfeil forårsaket av parallell utførelse.

Hvis du virkelig ønsker parallell utførelse, kan du påkalle executeOnExecutor (java.util.concurrent.Executor, Object ) medTHREAD_POOL_EXECUTOR. "

Fra mitt perspektiv er dette litt motintuitivt. I tillegg vil jeg ønske at en atferdsendring i denne størrelsesorden kunngjøres ved å bla i trompeter og et rop av Hør dere! Hør dere! Likevel er det en enkel løsning å bevare atferden som er sett på Eclair.

 int currentapiVersion = android.os.Build.VERSION. SDK_INT ; 
 for ( int i = 0; i <5; i ++) { 
 AsyncTask oppgave = new AsyncTask1 (); 
 if (currentapiVersion> = 
 android.os.Build.VERSION_CODES. HONEYCOMB ) {task.executeOnExecutor (AsyncTask. THREAD_POOL_EXECUTOR ); 
 } annet { 
 task.execute (); 
 } 
 } 
Som du ser av diagrammet nedenfor, ble utføringshastigheten gjenopprettet ( figur B ). Figur B

For min spesielle applikasjon var ikke virkningen stor hvis endringen i atferd har skjedd siden utgivelsen av Honeycomb, og jeg akkurat nå hører om det. Likevel, som de fleste utviklere, ønsker jeg å gi brukerne en optimal opplevelse. Jeg antok (feil) at et nyere operativsystem betydde at ting ville løpe minst med samme hastighet, om ikke raskere. Lært en lekse.

Hvis du ikke har sett på AsyncTask-dokumentene på en stund, anbefaler jeg å kjenne deg igjen med dem. I min kode er det lite sannsynlig at jeg vil utføre asynkrone oppgaver i fremtiden uten å bruke onExecutor-metoden.

© Copyright 2021 | pepebotifarra.com