Änderungen im Verhalten von Android AsyncTask sollten Sie kennen

Google möchte, dass Sie das Android AsyncTask-Muster lieben. Ich gebe zu, dass ich aus einem eingebetteten C / C ++ - Hintergrund heraus ein wenig skeptisch war, meine lang laufenden E / A an einen Black-Boxed-Thread-Pool zu übergeben. Mit der Zeit schätzte ich die Klasse und ihre Einfachheit. Es hat gut funktioniert und ich musste mich nicht damit täuschen.

In der vergangenen Woche bin ich jedoch auf ein unerwartetes Verhalten gestoßen. Ein Benutzer meldete sehr langsame E / A in einer meiner Anwendungen, nachdem er ein Upgrade von einem älteren Gerät auf ein neueres durchgeführt hatte. Dies war das Gegenteil von dem, was man erwarten würde, also habe ich schnell einen rudimentären Test zusammengestellt, um einige Metriken zu ermitteln.

Betrachten Sie das folgende Codefragment:

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

Auch ohne zu wissen, was in der AysncTask1-Implementierung vor sich geht, ist es meines Erachtens beabsichtigt, fünf dieser Aufgaben zu starten. Für meinen Test habe ich einige lang laufende E / A simuliert, indem ich die doInBackground-Funktion von AsyncTask1 überschrieben habe, um 1.000 Millisekunden lang zu schlafen.

 @Override 
 geschütztes Objekt doInBackground (Object ... arg0) try { 
 Faden. Schlaf ( ONE_SECOND ); 
 } catch (InterruptedException e) {// TODO Automatisch generierter catch-Block 
 e.printStackTrace (); 
 }} 
 return null ; 
 }} 
Nachdem ich einige grundlegende Debug-Timer eingegeben hatte, führte ich den Code auf zwei AVD-Instanzen aus: einer mit Eclair (Android 2.0) und einer mit Jelly Bean (Android 4.2). Die Ergebnisse haben mich überrascht. Überzeugen Sie sich selbst ( Abbildung A ). Abbildung A.

Das ist richtig - Android 2.0 hat die neueste und beste Version des Betriebssystems hinterlassen, die Staub frisst. Sie müssen nicht so klug sein, um die Verzögerung von einer Sekunde, die wir in unserer AsyncTask fest codiert haben, mit den fünf Iterationen unserer for-Schleife zu multiplizieren, um zu erraten, was passiert: Android führt die Aufgaben seriell statt parallel aus. Ich fing an, in den Foren herumzustöbern und wurde schließlich zurück zu Googles AsyncTask-Dokumentation geleitet. Etwa ein Drittel des Seitenabschnitts finden Sie den folgenden Hinweis:

"Beginnend mit HONEYCOMB werden Aufgaben in einem einzelnen Thread ausgeführt, um häufige Anwendungsfehler zu vermeiden, die durch parallele Ausführung verursacht werden.

Wenn Sie wirklich eine parallele Ausführung wünschen, können Sie executeOnExecutor (java.util.concurrent.Executor, Object ) mit THREAD_POOL_EXECUTOR aufrufen. "

Aus meiner Sicht ist dies ein wenig eingängig. Außerdem möchte ich, dass eine Verhaltensänderung dieser Größenordnung durch dröhnende Trompeten und einen Schrei von Hear ye angekündigt wird ! Höre dich! Trotzdem ist es eine einfache Lösung, das auf Eclair beobachtete Verhalten beizubehalten.

 int currentapiVersion = android.os.Build.VERSION. SDK_INT ; 
 für ( int i = 0; i <5; i ++) { 
 AsyncTask task = new AsyncTask1 (); 
 if (currentapiVersion> = 
 android.os.Build.VERSION_CODES. HONEYCOMB ) {task.executeOnExecutor (AsyncTask. THREAD_POOL_EXECUTOR ); 
 } else { 
 task.execute (); 
 }} 
 }} 
Wie Sie der folgenden Tabelle entnehmen können, wurde die Ausführungsgeschwindigkeit wiederhergestellt ( Abbildung B ). Abbildung B.

Für meine spezielle Anwendung waren die Auswirkungen nicht groß, wenn sich das Verhalten seit der Veröffentlichung von Honeycomb geändert hat und ich gerade davon höre. Trotzdem möchte ich, wie die meisten Entwickler, den Benutzern eine optimale Erfahrung bieten. Ich nahm (fälschlicherweise) an, dass ein neueres Betriebssystem bedeutet, dass die Dinge mindestens mit der gleichen Geschwindigkeit laufen würden, wenn nicht sogar schneller. Lektion gelernt.

Wenn Sie sich die AsyncTask-Dokumente eine Weile nicht angesehen haben, empfehle ich Ihnen, sich erneut mit ihnen vertraut zu machen. In meinem Code ist es unwahrscheinlich, dass ich in Zukunft asynchrone Aufgaben ausführen werde, ohne die onExecutor-Methode zu verwenden.

© Copyright 2021 | pepebotifarra.com