Android AsyncTask gedragsveranderingen die u moet weten

Google wil dat je dol bent op het Android AsyncTask-patroon. Ik geef toe dat ik, uitgaande van een ingebedde C / C ++ -achtergrond, een beetje sceptisch was over het overdragen van mijn langlopende I / O aan een threadbox met een zwarte doos. Na verloop van tijd waardeerde ik de klasse en de eenvoud ervan. Het werkte goed en ik hoefde er niet voor de gek te houden.

De afgelopen week kwam ik echter onverwacht gedrag tegen. Een gebruiker meldde zeer trage I / O op een van mijn applicaties nadat hij een upgrade had uitgevoerd van een ouder naar een nieuwer apparaat. Dit was het tegenovergestelde van wat je zou verwachten, dus ik gooide snel een rudimentaire test samen om een ​​aantal statistieken te trekken.

Overweeg het volgende codefragment:

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

Zelfs zonder te weten wat er gaande is in de AysncTask1-implementatie, is het naar mijn mening de bedoeling om vijf van deze taken te starten. Dus voor mijn test heb ik een aantal langlopende I / O gesimuleerd door de doInBackground-functie van AsyncTask1 voor 1000 milliseconden te laten inslapen.

 @ Override 
 beschermd object doInBackground (Object ... arg0) probeer { 
 Draad. slaap ( ONE_SECOND ); 
 } vangst (InterruptedException e) {// TODO Automatisch gegenereerd vangstblok 
 e.printStackTrace (); 
 } 
 terugkeer null ; 
 } 
Nadat ik enkele eenvoudige debug-timers had ingevoerd, voerde ik de code uit op twee AVD-exemplaren: één met Eclair (Android 2.0) en één met Jelly Bean (Android 4.2). De resultaten verrasten me. Kijk zelf ( figuur A ). Figuur A

Dat klopt - Android 2.0 heeft de nieuwste en beste versie van het besturingssysteem achtergelaten. Je hoeft niet zo scherpzinnig te zijn om de vertraging van één seconde die we in onze AsyncTask hebben gecodeerd te vermenigvuldigen met de vijf iteraties van onze for-loop om te raden wat er gebeurt: Android voert de taken serieel uit in plaats van parallel. Ik begon rond te snuffelen op de forums en werd uiteindelijk teruggeleid naar de AsyncTask-documentatie van Google. Ongeveer een derde van de weg onderaan de pagina vindt u de volgende opmerking:

"Beginnend met HONEYCOMB worden taken uitgevoerd op een enkele thread om veelvoorkomende applicatiefouten veroorzaakt door parallelle uitvoering te voorkomen.

Als je echt parallelle uitvoering wilt, kun je executeOnExecutor (java.util.concurrent.Executor, Object ) aanroepen metTHREAD_POOL_EXECUTOR. "

Vanuit mijn perspectief is dit een beetje contra-intuïtief. Bovendien wil ik een gedragsverandering van deze omvang aankondigen door trompetten te blazen en een schreeuw van Hoor! Hoor! Desalniettemin is het behoud van het gedrag op Eclair een eenvoudige oplossing.

 int currentapiVersion = android.os.Build.VERSION. SDK_INT ; 
 voor ( int i = 0; i <5; i ++) { 
 AsyncTask task = new AsyncTask1 (); 
 if (currentapiVersion> = 
 android.os.Build.VERSION_CODES. HONEYCOMB ) {task.executeOnExecutor (AsyncTask. THREAD_POOL_EXECUTOR ); 
 } anders { 
 task.execute (); 
 } 
 } 
Zoals u in de onderstaande grafiek kunt zien, werd de uitvoeringssnelheid hersteld ( Afbeelding B ). Figuur B

Voor mijn specifieke toepassing was de impact niet enorm als de verandering in gedrag al bestaat sinds de release van Honeycomb en ik hoor het nu pas. Toch wil ik, net als de meeste ontwikkelaars, gebruikers een optimale ervaring bieden. Ik ging ervan uit (ten onrechte) dat een nieuwer besturingssysteem betekende dat dingen op zijn minst op dezelfde snelheid zouden lopen, zo niet sneller. Lesje geleerd.

Als u de AsyncTask-documenten een tijdje niet hebt bekeken, raad ik u aan om ze opnieuw te leren kennen. In mijn code is het onwaarschijnlijk dat ik in de toekomst asynchrone taken zal uitvoeren zonder de onExecutor-methode te gebruiken.

© Copyright 2020 | mobilegn.com