Android AsyncTask-beteende ändras du bör känna till

Google vill att du ska älska sitt Android AsyncTask-mönster. Jag medger att jag, från en inbäddad C / C ++ bakgrund, var lite skeptisk när jag överlämnade min långvariga I / O till en svartboxad trådpool. Men med tiden uppskattade jag klassen och dess enkelhet. Det fungerade bra, och jag behövde inte lura det.

Men den senaste veckan stötte jag på något oväntat beteende. En användare rapporterade mycket långsam I / O på en av mina applikationer efter att han uppgraderade från en äldre enhet till en nyare. Detta var motsatsen till vad man kan förvänta sig, så jag slog snabbt samman ett rudimentärt test för att dra några mätvärden.

Tänk på följande kodavsnitt:

 för ( int i = 0; i <5; i ++) { 
 AsyncTask1 uppgift = ny AsyncTask1 (); 
 task.execute (); 
 } 

Även utan att veta vad som händer inom AysncTask1-implementeringen är enligt min mening avsikten att starta fem av dessa uppgifter. Så i syftet med mitt test simulerade jag lite långvarig I / O genom att åsidosätta doInBackground-funktionen i AsyncTask1 för att sova i 1 000 millisekunder.

 @Åsidosätta 
 skyddad objekt doInBackground (Object ... arg0) försök { 
 Tråd. sömn ( ONE_SECOND ); 
 } catch (InterruptException e) {// TODO Auto-genererad fångstblock 
 e.printStackTrace (); 
 } 
 return null ; 
 } 
Efter att ha lagt in några grundläggande felsökningstimrar körde jag koden i två AVD-instanser: en som kör Eclair (Android 2.0) och en som kör Jelly Bean (Android 4.2). Resultaten förvånade mig. Titta själv ( figur A ). Figur A

Det stämmer - Android 2.0 lämnade den senaste och bästa versionen av OS som äter damm. Du behöver inte vara så skarp för att multiplicera en sekunders fördröjning som vi hårdkodade in i vår AsyncTask med de fem iterationerna i vår for-loop för att gissa vad som händer: Android kör uppgifterna seriellt istället för parallellt. Jag började pirka på forumen och riktades så småningom tillbaka till Googles AsyncTask-dokumentation. Ungefär en tredjedel av vägen ner på sidan hittar du följande anmärkning:

"Från och med HONEYCOMB utförs uppgifter på en enda tråd för att undvika vanliga applikationsfel orsakade av parallell körning.

Om du verkligen vill ha parallellkörning kan du åberopa executeOnExecutor (java.util.concurrent.Executor, Object ) medTHREAD_POOL_EXECUTOR. "

Ur mitt perspektiv är detta lite motsatt. Dessutom skulle jag vilja att en beteendeförändring av den här storleken ska tillkännages genom att trasiga trumpeter och ett skrik av Hör ni! Hör ni! Ändå är det en enkel lösning att bevara beteendet som ses på Eclair.

 int currentapiVersion = android.os.Build.VERSION. SDK_INT ; 
 för ( int i = 0; i <5; i ++) { 
 AsyncTask uppgift = new AsyncTask1 (); 
 if (currentapiVersion> = 
 android.os.Build.VERSION_CODES. HONEYCOMB ) {task.executeOnExecutor (AsyncTask. THREAD_POOL_EXECUTOR ); 
 } annat { 
 task.execute (); 
 } 
 } 
Som du kan se från diagrammet nedan återställdes exekveringshastigheten ( figur B ). Figur B

För min speciella applikation var inte effekterna enorma om förändringarna i beteende har skett sedan utgivningen av Honeycomb och jag hör just nu om det. Jag vill fortfarande, som de flesta utvecklare, ge användarna en optimal upplevelse. Jag antog (felaktigt) att ett nyare operativsystem innebar att saker skulle gå åtminstone med samma hastighet, om inte snabbare. Lärdom.

Om du inte har tittat på AsyncTask-dokumenten på ett tag rekommenderar jag att du målar om dig själv med dem. I min kod är det osannolikt att jag kommer att utföra asynkrona uppgifter i framtiden utan att använda onExecutor-metoden.

© Copyright 2020 | mobilegn.com