Android
AsyncTask
Suche…
Parameter
Parameter | Einzelheiten |
---|---|
Params | die Art der Parameter, die bei der Ausführung an die Task gesendet werden. |
Fortschritt | die Art der Fortschrittseinheiten, die während der Hintergrundberechnung veröffentlicht wurden |
Ergebnis | die Art des Ergebnisses der Hintergrundberechnung. |
Grundlegende Verwendung
In Android Aktivitäten und Dienstleistungen sind die meisten Rückrufe auf der Flucht Hauptthread . Dies macht es einfach, die Benutzeroberfläche zu aktualisieren, aber das Ausführen von prozessor- oder E / A-schweren Tasks im Haupt-Thread kann dazu führen, dass Ihre Benutzeroberfläche angehalten wird und nicht mehr reagiert ( offizielle Dokumentation dazu, was dann passiert).
Sie können dies beheben, indem Sie diese schwereren Aufgaben in einem Hintergrundthread ablegen.
Eine Möglichkeit hierzu ist die Verwendung einer AsyncTask , die ein Framework bereitstellt , das die einfache Verwendung eines Hintergrund-Threads erleichtert und UI-Thread-Tasks vor, während und nach Abschluss der Arbeit des Hintergrund-Threads ausführt.
Methoden, die beim Erweitern von AsyncTask
überschrieben werden AsyncTask
:
-
onPreExecute()
:onPreExecute()
im UI-Thread aufgerufen, bevor die Task ausgeführt wird -
doInBackground()
: auf dem Hintergrund - Thread aufgerufen unmittelbar nachonPreExecute()
beendet die Ausführung. -
onProgressUpdate()
:onProgressUpdate()
nach einem Aufruf vonpublishProgress(Progress...)
im UI-Thread aufgerufen. -
onPostExecute()
:onPostExecute()
im UI-Thread aufgerufen, nachdem die Hintergrundberechnung abgeschlossen ist
Beispiel
public class MyCustomAsyncTask extends AsyncTask<File, Void, String> {
@Override
protected void onPreExecute(){
// This runs on the UI thread before the background thread executes.
super.onPreExecute();
// Do pre-thread tasks such as initializing variables.
Log.v("myBackgroundTask", "Starting Background Task");
}
@Override
protected String doInBackground(File... params) {
// Disk-intensive work. This runs on a background thread.
// Search through a file for the first line that contains "Hello", and return
// that line.
try (Scanner scanner = new Scanner(params[0])) {
while (scanner.hasNextLine()) {
final String line = scanner.nextLine();
publishProgress(); // tell the UI thread we made progress
if (line.contains("Hello")) {
return line;
}
}
return null;
}
}
@Override
protected void onProgressUpdate(Void...p) {
// Runs on the UI thread after publishProgress is invoked
Log.v("Read another line!")
}
@Override
protected void onPostExecute(String s) {
// This runs on the UI thread after complete execution of the doInBackground() method
// This function receives result(String s) returned from the doInBackground() method.
// Update UI with the found string.
TextView view = (TextView) findViewById(R.id.found_string);
if (s != null) {
view.setText(s);
} else {
view.setText("Match not found.");
}
}
}
Verwendungszweck:
MyCustomAsyncTask asyncTask = new MyCustomAsyncTask<File, Void, String>();
// Run the task with a user supplied filename.
asyncTask.execute(userSuppliedFilename);
oder einfach:
new MyCustomAsyncTask().execute(userSuppliedFilename);
Hinweis
Bei der Definition einer AsyncTask
wir drei Typen zwischen < >
Klammern übergeben.
Definiert als <Params, Progress, Result>
(siehe Abschnitt Parameter )
Im vorherigen Beispiel haben wir die Typen <File, Void, String>
:
AsyncTask<File, Void, String>
// Params has type File
// Progress has unused type
// Result has type String
Void
wird verwendet, wenn Sie einen Typ als nicht verwendet markieren möchten.
Beachten Sie, dass Sie keine primitiven Typen (dh int
, float
und 6 andere) als Parameter übergeben können. In solchen Fällen sollten Sie ihre Wrapper-Klassen übergeben , z. B. Integer
statt int
oder Float
statt float
.
Der AsyncTask- und Activity-Lebenszyklus
AsyncTasks folgen nicht dem Lebenszyklus der Aktivitätsinstanzen. Wenn Sie eine AsyncTask in einer Aktivität starten und das Gerät drehen, wird die Aktivität zerstört und eine neue Instanz erstellt. Aber die AsyncTask wird nicht sterben. Es wird weiterleben, bis es fertig ist.
Lösung: AsyncTaskLoader
Eine Unterklasse von Loadern ist der AsyncTaskLoader. Diese Klasse hat die gleiche Funktion wie die AsyncTask, jedoch viel besser. Es kann Aktivitätskonfigurationsänderungen einfacher handhaben und verhält sich innerhalb der Lebenszyklen von Fragmenten und Aktivitäten. Das Schöne ist, dass der AsyncTaskLoader in jeder Situation verwendet werden kann, in der die AsyncTask verwendet wird. Immer wenn Daten in den Speicher geladen werden müssen, damit die Aktivität / das Fragment verarbeitet werden kann, kann der AsyncTaskLoader die Aufgabe besser erfüllen.
AsyncTask abbrechen
YourAsyncTask task = new YourAsyncTask();
task.execute();
task.cancel();
Dies stoppt Ihre Aufgabe nicht, wenn sie gerade ausgeführt wird. Sie setzt lediglich das Flag " isCancelled()
das überprüft werden kann, indem der Rückgabewert von isCancelled()
überprüft wird (vorausgesetzt, Ihr Code läuft derzeit).
class YourAsyncTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
while(!isCancelled()) {
... doing long task stuff
//Do something, you need, upload part of file, for example
if (isCancelled()) {
return null; // Task was detected as canceled
}
if (yourTaskCompleted) {
return null;
}
}
}
}
Hinweis
Wenn eine AsyncTask abgebrochen wird, während noch doInBackground(Params... params)
wird, wird die Methode onPostExecute(Result result)
NICHT nach doInBackground(Params... params)
. Die AsyncTask ruft stattdessen onCancelled(Result result)
auf, um anzuzeigen, dass die Aufgabe während der Ausführung abgebrochen wurde.
Veröffentlichungsfortschritt
Manchmal müssen wir den Fortschritt der von einer AsyncTask
Berechnung AsyncTask
. Dieser Fortschritt kann durch eine Zeichenfolge, eine Ganzzahl usw. dargestellt werden. Dazu müssen wir zwei Funktionen verwenden. Zuerst müssen wir die onProgressUpdate
Funktion onProgressUpdate
, deren Parametertyp dem zweiten Typparameter unserer AsyncTask
.
class YourAsyncTask extends AsyncTask<URL, Integer, Long> {
@Override
protected void onProgressUpdate(Integer... args) {
setProgressPercent(args[0])
}
}
Zweitens müssen wir die Funktion publishProgress
notwendigerweise auf der doInBackground
Funktion, und das ist alles, tun die vorherige Methode alle den Job.
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
}
return totalSize;
}
Laden Sie das Bild mit AsyncTask in Android herunter
In diesem Lernprogramm wird erläutert, wie Sie Image mit AsyncTask in Android herunterladen. Das Beispiel unten zeigt ein Bild zum Herunterladen, während der Download während des Fortschritts angezeigt wird.
Grundlegendes zu Android AsyncTask
Mit der asynchronen Task können Sie MultiThreading implementieren, ohne die Hände in Threads zu verschmutzen. AsyncTask ermöglicht die ordnungsgemäße und einfache Verwendung des UI-Threads. Es ermöglicht Hintergrundoperationen und die Weitergabe der Ergebnisse an den UI-Thread. Wenn Sie etwas Isoliertes in Bezug auf die Benutzeroberfläche tun, beispielsweise Daten herunterladen, um sie in einer Liste anzuzeigen, fahren Sie fort und verwenden Sie AsyncTask.- AsyncTasks sollten idealerweise für kurze Operationen (höchstens einige Sekunden) verwendet werden.
- Eine asynchrone Task wird durch 3 generische Typen definiert, die als Params, Progress und Result bezeichnet werden, sowie 4 Schritte, die als
onPreExecute()
,doInBackground()
,onProgressUpdate()
undonPostExecute()
. - In
onPreExecute()
Sie Code definieren, der ausgeführt werden muss, bevor die Hintergrundverarbeitung beginnt. - doInBackground enthält Code, der im Hintergrund ausgeführt werden muss. Hier in
doInBackground()
wir die Ergebnisse mit der Methode publishProgress () mehrmals an den Ereignisthread senden. Wenn die Hintergrundverarbeitung abgeschlossen ist, können wir die Ergebnisse einfach zurückgeben. -
onProgressUpdate()
Methode empfängt Fortschrittsaktualisierungen von der MethodedoInBackground()
, die über diepublishProgress()
Methode veröffentlicht wird. Diese Methode kann diese Fortschrittsaktualisierung zum Aktualisieren des Ereignisthreads verwenden -
onPostExecute()
-Methode verarbeitet Ergebnisse, die von derdoInBackground()
-Methode zurückgegeben werden. - Die generischen Typen sind
- Params, der Typ der Parameter, die bei der Ausführung an die Task gesendet werden
- Fortschritt, der Typ der Fortschrittseinheiten, die während der Hintergrundberechnung veröffentlicht wurden.
- Result ist die Art des Ergebnisses der Hintergrundberechnung.
- Wenn ein asynchroner Task keine Typen verwendet, kann er als ungültiger Typ markiert werden.
- Eine laufende async-Task kann abgebrochen werden, indem
cancel(boolean)
Methodecancel(boolean)
wird.
Bild mit Android AsyncTask herunterladen
Ihr XML-Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/downloadButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Click Here to Download" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="Your image will appear here" />
</LinearLayout>
.java-Klasse
package com.javatechig.droid;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
public class ImageDownladerActivity extends Activity {
private ImageView downloadedImg;
private ProgressDialog simpleWaitDialog;
private String downloadUrl = "http://www.9ori.com/store/media/images/8ab579a656.jpg";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.asynch);
Button imageDownloaderBtn = (Button) findViewById(R.id.downloadButton);
downloadedImg = (ImageView) findViewById(R.id.imageView);
imageDownloaderBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
new ImageDownloader().execute(downloadUrl);
}
});
}
private class ImageDownloader extends AsyncTask {
@Override
protected Bitmap doInBackground(String... param) {
// TODO Auto-generated method stub
return downloadBitmap(param[0]);
}
@Override
protected void onPreExecute() {
Log.i("Async-Example", "onPreExecute Called");
simpleWaitDialog = ProgressDialog.show(ImageDownladerActivity.this,
"Wait", "Downloading Image");
}
@Override
protected void onPostExecute(Bitmap result) {
Log.i("Async-Example", "onPostExecute Called");
downloadedImg.setImageBitmap(result);
simpleWaitDialog.dismiss();
}
private Bitmap downloadBitmap(String url) {
// initilize the default HTTP client object
final DefaultHttpClient client = new DefaultHttpClient();
//forming a HttpGet request
final HttpGet getRequest = new HttpGet(url);
try {
HttpResponse response = client.execute(getRequest);
//check 200 OK for success
final int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK) {
Log.w("ImageDownloader", "Error " + statusCode +
" while retrieving bitmap from " + url);
return null;
}
final HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream inputStream = null;
try {
// getting contents from the stream
inputStream = entity.getContent();
// decoding stream data back into image Bitmap that android understands
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
} finally {
if (inputStream != null) {
inputStream.close();
}
entity.consumeContent();
}
}
} catch (Exception e) {
// You Could provide a more explicit error message for IOException
getRequest.abort();
Log.e("ImageDownloader", "Something went wrong while" +
" retrieving bitmap from " + url + e.toString());
}
return null;
}
}
}
Da es derzeit kein Kommentarfeld für Beispiele gibt (oder ich habe es nicht gefunden oder ich habe keine Erlaubnis dafür), hier ein Kommentar dazu:
Dies ist ein gutes Beispiel für die Verwendung von AsyncTask.
Allerdings hat das Beispiel derzeit Probleme mit
- mögliche Speicherlecks
- App stürzt ab, wenn kurz vor Beendigung der asynchronen Task eine Bildschirmrotation stattgefunden hat.
Für Details siehe:
- Übergeben Sie die Aktivität als WeakReference, um Speicherverluste zu vermeiden
- http://stackoverflow.com/documentation/android/117/asynctask/5377/possible-problems-mit-inner-async-tasks
- Vermeiden Sie undichte Aktivitäten mit AsyncTask
Übergeben Sie die Aktivität als WeakReference, um Speicherverluste zu vermeiden
Es ist üblich, dass eine AsyncTask einen Verweis auf die Aktivität erfordert, die sie aufgerufen hat.
Wenn die AsyncTask eine innere Klasse der Aktivität ist, können Sie direkt auf sie und alle Member-Variablen / -Methoden verweisen.
Wenn die AsyncTask jedoch keine innere Klasse der Aktivität ist, müssen Sie eine Aktivitätsreferenz an die AsyncTask übergeben. Wenn Sie dies tun, besteht ein mögliches Problem möglicherweise darin, dass die AsyncTask den Verweis der Aktivität behält, bis die AsyncTask ihre Arbeit in ihrem Hintergrundthread abgeschlossen hat. Wenn die Aktivität beendet oder beendet wird, bevor die Hintergrundarbeit des AsyncTask-Threads abgeschlossen ist, hat die AsyncTask immer noch ihren Verweis auf die Aktivität. Daher kann keine Sammlung von Speicherbereinigungen erfolgen.
Dies führt zu einem Speicherverlust.
Um dies zu verhindern, verwenden Sie eine WeakReference in der AsyncTask, anstatt einen direkten Verweis auf die Aktivität zu haben.
Hier ist ein Beispiel für AsyncTask, das eine WeakReference verwendet:
private class MyAsyncTask extends AsyncTask<String, Void, Void> {
private WeakReference<Activity> mActivity;
public MyAsyncTask(Activity activity) {
mActivity = new WeakReference<Activity>(activity);
}
@Override
protected void onPreExecute() {
final Activity activity = mActivity.get();
if (activity != null) {
....
}
}
@Override
protected Void doInBackground(String... params) {
//Do something
String param1 = params[0];
String param2 = params[1];
return null;
}
@Override
protected void onPostExecute(Void result) {
final Activity activity = mActivity.get();
if (activity != null) {
activity.updateUI();
}
}
}
AsyncTask aus einer Aktivität aufrufen:
new MyAsyncTask(this).execute("param1", "param2");
AsyncTask aus einem Fragment aufrufen:
new MyAsyncTask(getActivity()).execute("param1", "param2");
Reihenfolge der Ausführung
Bei der ersten Einführung wurden AsyncTasks
seriell in einem einzigen Hintergrundthread ausgeführt. Beginnend mit DONUT
wurde dies in einen Pool von Threads geändert, sodass mehrere Aufgaben parallel ausgeführt werden können. Beginnend mit HONEYCOMB
werden Aufgaben in einem einzelnen Thread ausgeführt, um häufige Anwendungsfehler zu vermeiden, die durch die parallele Ausführung verursacht werden.
Wenn Sie wirklich eine parallele Ausführung wünschen, können Sie den executeOnExecutor(java.util.concurrent.Executor, Object[])
mit THREAD_POOL_EXECUTOR
.
SERIAL_EXECUTOR -> Ein Executor, der Aufgaben nacheinander in serieller Reihenfolge ausführt.
THREAD_POOL_EXECUTOR -> Ein Executor, mit dem Aufgaben parallel ausgeführt werden können.
Probe :
Task task = new Task();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, data);
else
task.execute(data);
AsyncTask: Serienausführung und parallele Ausführung der Aufgabe
AsyncTask ist eine abstrakte Klasse und erbt nicht die Thread
Klasse. Es verfügt über eine abstrakte Methode doInBackground(Params... params)
, die zur Ausführung der Aufgabe überschrieben wird. Diese Methode wird aus AsyncTask.call()
aufgerufen.
Executor sind Teil des Pakets java.util.concurrent
.
Außerdem enthält AsyncTask 2 Executor
Dateien
THREAD_POOL_EXECUTOR
Es verwendet Worker-Threads, um die Aufgaben parallel auszuführen.
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
SERIAL_EXECUTOR
Er führt die Aufgabe seriell aus, dh eine nach der anderen.
private static class SerialExecutor implements Executor { }
Beide Executor
THREAD_POOL_EXECUTOR
sind statisch , daher gibt es nur ein THREAD_POOL_EXECUTOR
und ein SerialExecutor
Objekt. Sie können jedoch mehrere AsyncTask
Objekte erstellen.
Wenn Sie versuchen, mehrere Hintergrundaufgaben mit dem Standard-Executor ( SerialExecutor
) SerialExecutor
, werden diese Aufgaben in die Warteschlange gestellt und seriell ausgeführt.
Wenn Sie versuchen, mehrere Hintergrundaufgaben mit THREAD_POOL_EXECUTOR
, werden diese parallel ausgeführt.
Beispiel:
public class MainActivity extends Activity {
private Button bt;
private int CountTask = 0;
private static final String TAG = "AsyncTaskExample";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = (Button) findViewById(R.id.button);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
BackgroundTask backgroundTask = new BackgroundTask ();
Integer data[] = { ++CountTask, null, null };
// Task Executed in thread pool ( 1 )
backgroundTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, data);
// Task executed Serially ( 2 )
// Uncomment the below code and comment the above code of Thread
// pool Executor and check
// backgroundTask.execute(data);
Log.d(TAG, "Task = " + (int) CountTask + " Task Queued");
}
});
}
private class BackgroundTask extends AsyncTask<Integer, Integer, Integer> {
int taskNumber;
@Override
protected Integer doInBackground(Integer... integers) {
taskNumber = integers[0];
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d(TAG, "Task = " + taskNumber + " Task Running in Background");
publishProgress(taskNumber);
return null;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(Integer aLong) {
super.onPostExecute(aLong);
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
Log.d(TAG, "Task = " + (int) values[0]
+ " Task Execution Completed");
}
}
}
Ausführen Klicken Sie mehrmals auf die Schaltfläche, um eine Aufgabe zu starten und das Ergebnis anzuzeigen.
Im Thread-Pool ausgeführte Aufgabe (1)
Jede Aufgabe dauert 1000 ms.
Bei t = 36s werden die Aufgaben 2, 3 und 4 in die Warteschlange gestellt und gestartet, auch weil sie parallel ausgeführt werden.
08-02 19:48:35.815: D/AsyncTaskExample(11693): Task = 1 Task Queued
08-02 19:48:35.815: D/AsyncTaskExample(11693): Task = 1 Task Running in Background
08-02 19:48:**36.025**: D/AsyncTaskExample(11693): Task = 2 Task Queued
08-02 19:48:**36.025**: D/AsyncTaskExample(11693): Task = 2 Task Running in Background
08-02 19:48:**36.165**: D/AsyncTaskExample(11693): Task = 3 Task Queued
08-02 19:48:**36.165**: D/AsyncTaskExample(11693): Task = 3 Task Running in Background
08-02 19:48:**36.325**: D/AsyncTaskExample(11693): Task = 4 Task Queued
08-02 19:48:**36.325**: D/AsyncTaskExample(11693): Task = 4 Task Running in Background
08-02 19:48:**36.815**: D/AsyncTaskExample(11693): Task = 1 Task Execution Completed
08-02 19:48:**36.915**: D/AsyncTaskExample(11693): Task = 5 Task Queued
08-02 19:48:**36.915**: D/AsyncTaskExample(11693): Task = 5 Task Running in Background
08-02 19:48:37.025: D/AsyncTaskExample(11693): Task = 2 Task Execution Completed
08-02 19:48:37.165: D/AsyncTaskExample(11693): Task = 3 Task Execution Completed
----------
Kommentar- Task Executed in thread pool
(1) ausgeführt wird, und uncomment Task executed Serially
(2).
Ausführen Klicken Sie mehrmals auf die Schaltfläche, um eine Aufgabe zu starten und das Ergebnis anzuzeigen.
Die Aufgabe wird seriell ausgeführt, daher wird jede Aufgabe gestartet, nachdem die Ausführung der aktuellen Aufgabe abgeschlossen ist. Wenn die Ausführung von Task 1 abgeschlossen ist, wird daher nur Task 2 im Hintergrund ausgeführt. Und umgekehrt.
08-02 19:42:57.505: D/AsyncTaskExample(10299): Task = 1 Task Queued
08-02 19:42:57.505: D/AsyncTaskExample(10299): Task = 1 Task Running in Background
08-02 19:42:57.675: D/AsyncTaskExample(10299): Task = 2 Task Queued
08-02 19:42:57.835: D/AsyncTaskExample(10299): Task = 3 Task Queued
08-02 19:42:58.005: D/AsyncTaskExample(10299): Task = 4 Task Queued
08-02 19:42:58.155: D/AsyncTaskExample(10299): Task = 5 Task Queued
08-02 19:42:58.505: D/AsyncTaskExample(10299): Task = 1 Task Execution Completed
08-02 19:42:58.505: D/AsyncTaskExample(10299): Task = 2 Task Running in Background
08-02 19:42:58.755: D/AsyncTaskExample(10299): Task = 6 Task Queued
08-02 19:42:59.295: D/AsyncTaskExample(10299): Task = 7 Task Queued
08-02 19:42:59.505: D/AsyncTaskExample(10299): Task = 2 Task Execution Completed
08-02 19:42:59.505: D/AsyncTaskExample(10299): Task = 3 Task Running in Background
08-02 19:43:00.035: D/AsyncTaskExample(10299): Task = 8 Task Queued
08-02 19:43:00.505: D/AsyncTaskExample(10299): Task = 3 Task Execution Completed
08-02 19:43:**00.505**: D/AsyncTaskExample(10299): Task = 4 Task Running in Background
08-02 19:43:**01.505**: D/AsyncTaskExample(10299): Task = 4 Task Execution Completed
08-02 19:43:**01.515**: D/AsyncTaskExample(10299): Task = 5 Task Running in Background
08-02 19:43:**02.515**: D/AsyncTaskExample(10299): Task = 5 Task Execution Completed
08-02 19:43:**02.515**: D/AsyncTaskExample(10299): Task = 6 Task Running in Background
08-02 19:43:**03.515**: D/AsyncTaskExample(10299): Task = 7 Task Running in Background
08-02 19:43:**03.515**: D/AsyncTaskExample(10299): Task = 6 Task Execution Completed
08-02 19:43:04.515: D/AsyncTaskExample(10299): Task = 8 Task Running in Background
08-02 19:43:**04.515**: D/AsyncTaskExample(10299): Task = 7 Task Execution Completed