Sök…


parametrar

Parameter detaljer
params typen av parametrar som skickas till uppgiften vid körning.
Framsteg vilken typ av framstegsenheter som publicerades under bakgrundsberäkningen
Resultat typen av resultatet av bakgrundsberäkningen.

Grundläggande användning

I Android- aktiviteter och tjänster körs de flesta återuppringningar på huvudtråden . Detta gör det enkelt att uppdatera användargränssnittet, men att köra processor- eller I / O-tunga uppgifter på huvudtråden kan få din UI att pausa och bli svarsfri ( officiell dokumentation om vad som sedan händer).

Du kan avhjälpa detta genom att lägga dessa tyngre uppgifter på en bakgrundstråd.

Ett sätt att göra detta är att använda en AsyncTask , som ger ett ramverk för att underlätta enkel användning av en bakgrundstråd, och även utföra UI-tråduppgifter före, under och efter bakgrunden Tråden har slutfört sitt arbete.

Metoder som kan åsidosättas vid AsyncTask :

  • onPreExecute() : aktiveras på UI-tråden innan uppgiften körs
  • doInBackground() : åberopas på bakgrundstråden omedelbart efter att onPreExecute() avslutats.
  • onProgressUpdate() : åberopas på UI-tråden efter ett samtal att publishProgress(Progress...) .
  • onPostExecute() : startas på UI-tråden efter att bakgrundsberäkningen är klar

Exempel

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.");
        }
    }

}

Användande:

MyCustomAsyncTask asyncTask = new MyCustomAsyncTask<File, Void, String>();
// Run the task with a user supplied filename.
asyncTask.execute(userSuppliedFilename);

eller bara:

new MyCustomAsyncTask().execute(userSuppliedFilename);

Notera

När vi definierar en AsyncTask vi passera tre typer mellan < > parentes.
Definierat som <Params, Progress, Result> (se avsnittet Parametrar )

I föregående exempel har vi använt typerna <File, Void, String> :

AsyncTask<File, Void, String>
// Params has type File
// Progress has unused type
// Result has type String

Void används när du vill markera en typ som oanvänd.

Observera att du inte kan skicka primitiva typer (dvs. int , float och 6 andra) som parametrar. I sådana fall bör du passera deras omslagsklasser , t.ex. Integer istället för int , eller Float istället för float .

Livscykeln AsyncTask och Activity

AsyncTasks följer inte aktivitetsinstansers livscykel. Om du startar en AsyncTask i en aktivitet och du roterar enheten kommer aktiviteten att förstöras och en ny instans skapas. Men AsyncTask kommer inte att dö. Den kommer att leva tills den är klar.

Lösning: AsyncTaskLoader

En underklass av Loaders är AsyncTaskLoader. Den här klassen utför samma funktion som AsyncTask, men mycket bättre. Den kan hantera förändringar av aktivitetskonfigurationen lättare och fungerar inom livscyklerna för fragment och aktiviteter. Det trevliga är att AsyncTaskLoader kan användas i alla situationer som AsyncTask används. När som helst data måste laddas i minnet för att Aktiviteten / Fragmentet ska kunna hanteras. AsyncTaskLoader kan göra jobbet bättre.

Avbryter AsyncTask

YourAsyncTask task = new YourAsyncTask();
task.execute();
task.cancel();

Detta stoppar inte din uppgift om den pågick, den ställer bara in den avbrutna flaggan som kan kontrolleras genom att kontrollera returvärdet för isCancelled() (förutsatt att din kod för närvarande körs) genom att göra detta:

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;
            }
        }
    }
}

Notera

Om en AsyncTask avbryts medan doInBackground(Params... params) fortfarande körs, kommer metoden onPostExecute(Result result) INTE att kallas efter att doInBackground(Params... params) kommer tillbaka. AsyncTask kommer istället att ringa onCancelled(Result result) att indikera att uppgiften avbröts under körningen.

Publiceringsframsteg

Ibland måste vi uppdatera framstegen för beräkningen som görs av en AsyncTask . Denna framsteg kan representeras av en sträng, ett heltal osv. För att göra detta måste vi använda två funktioner. Först måste vi ställa onProgressUpdate funktionen onProgressUpdate vars parametertyp är densamma som den andra AsyncTask vår AsyncTask .

class YourAsyncTask extends AsyncTask<URL, Integer, Long> {
    @Override
    protected void onProgressUpdate(Integer... args) {
        setProgressPercent(args[0])
    }
}

För det andra måste vi använda funktionen publishProgress nödvändigtvis på doInBackground funktionen, och det är allt, den tidigare metoden kommer att göra allt jobbet.

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;
 }

Ladda ner bild med AsyncTask i Android

Denna handledning förklarar hur du laddar ner bild med AsyncTask i Android. Exemplet nedladdningsbild medan du visar framstegsfältet under nedladdningen.

Förstå Android AsyncTask

Med Async-uppgiften kan du implementera MultiThreading utan att få Händerna smutsiga i trådar. AsyncTask möjliggör korrekt och enkel användning av UI-tråden. Det gör det möjligt att utföra bakgrundsoperationer och skicka resultaten på UI-tråden. Om du gör något isolerat relaterat till UI, till exempel nedladdning av data för att presenteras i en lista, gå vidare och använd AsyncTask.

  • AsyncTasks bör helst användas för korta operationer (högst några sekunder.)
  • En asynkron uppgift definieras av 3 generiska typer, kallad Params, Progress and Result, och fyra steg, som kallas onPreExecute() , doInBackground() , onProgressUpdate() och onPostExecute() .
  • I onPreExecute() du definiera kod som måste köras innan bakgrundsbearbetningen startar.
  • doInBackground har kod som måste utföras i bakgrunden, här i doInBackground() vi skicka resultat till flera gånger till händelsetråd med metoden publicProgress (), för att meddela att bakgrundsbearbetningen har avslutats kan vi returnera resultaten helt enkelt.
  • onProgressUpdate() får framstegsuppdateringar från doInBackground() , som publiceras via publishProgress() , och den här metoden kan använda denna framstegsuppdatering för att uppdatera händelsetråd
  • onPostExecute() hanterar resultat som returnerats med doInBackground() .
  • De generiska typerna som används är
    • Params, typen av parametrar som skickas till uppgiften vid körning
    • Framsteg, vilken typ av framstegsenheter som publicerades under bakgrundsberäkningen.
    • Resultat, typen av resultatet för bakgrundsberäkningen.
  • Om en async-uppgift inte använder några typer kan den markeras som Void-typ.
  • En löpande async-uppgift kan avbrytas genom att anropa cancel(boolean) metod.

Nedladdning av bild med Android AsyncTask

din .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 klass

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;
        }
    }
}

Eftersom det för närvarande inte finns något kommentarfält för exempel (eller jag inte har hittat det eller jag inte har behörighet för det) är här några kommentarer om detta:

Detta är ett bra exempel på vad som kan göras med AsyncTask.

Men exemplet har för närvarande problem med

  • möjliga minnesläckor
  • app-krasch om det fanns en skärmrotation strax innan async-uppgiften avslutades.

För detaljer se:

Passera aktivitet som WeakReference för att undvika minnesläckor

Det är vanligt att en AsyncTask kräver en hänvisning till den aktivitet som kallade den.

Om AsyncTask är en inre klass i aktiviteten, kan du referera till den och eventuella medlemsvariabler / metoder direkt.

Om AsyncTask emellertid inte är en inre klass i aktiviteten måste du skicka en aktivitetsreferens till AsyncTask. När du gör detta är ett potentiellt problem som kan uppstå att AsyncTask behåller referensen till aktiviteten tills AsyncTask har avslutat sitt arbete i sin bakgrundstråd. Om aktiviteten är klar eller dödas innan AsyncTasks bakgrundsgängarbetet är gjort, kommer AsyncTask fortfarande att ha sin referens till aktiviteten, och därför kan den inte samlas in.

Som ett resultat kommer detta att leda till ett minnesläckage.

Använd en WeakReference i AsyncTask istället för att direkt hänvisa till aktiviteten för att förhindra att detta sker.

Här är ett exempel på AsyncTask som använder en WeakReference:

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();
        }
    }
} 

Ringa AsyncTask från en aktivitet:

new MyAsyncTask(this).execute("param1", "param2");

Ringa AsyncTask från ett fragment:

new MyAsyncTask(getActivity()).execute("param1", "param2");

Bekräftelse av utförande

Vid första introduktionen AsyncTasks seriellt på en enda bakgrundstråd. Från och med DONUT ändrades detta till en pool av trådar som tillåter flera uppgifter att fungera parallellt. Från och med HONEYCOMB uppgifter på en enda tråd för att undvika vanliga applikationsfel orsakade av parallellkörning.

Om du verkligen vill ha parallellkörning kan du åberopa executeOnExecutor(java.util.concurrent.Executor, Object[]) med THREAD_POOL_EXECUTOR .

SERIAL_EXECUTOR -> En Executor som utför uppgifter en i taget i serieordning.

THREAD_POOL_EXECUTOR -> En kör som kan användas för att utföra uppgifter parallellt.

prov:

Task task = new Task();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
    task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, data);
else
    task.execute(data);

AsyncTask: Seriell exekvering och parallell exekvering av uppgift

AsyncTask är en abstrakt klass och ärver inte Thread . Den har en abstrakt metod doInBackground(Params... params) , som åsidosätts för att utföra uppgiften. Den här metoden kallas från AsyncTask.call() .

Executor ingår i java.util.concurrent paketet.

Dessutom innehåller AsyncTask 2 Executor s

THREAD_POOL_EXECUTOR

Den använder arbetartrådar för att utföra uppgifterna parallellt.

public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

SERIAL_EXECUTOR

Den utför uppgiften seriellt, dvs en efter en.

private static class SerialExecutor implements Executor { }

Båda Executor s är statiska , varför endast ett THREAD_POOL_EXECUTOR och ett SerialExecutor objekt finns, men du kan skapa flera AsyncTask objekt.

Om du försöker göra flera bakgrundsuppgifter med standardexekutorn ( SerialExecutor ) kommer dessa uppgifter att stå i kö och körs seriellt.

Om du försöker göra flera bakgrundsuppgifter med THREAD_POOL_EXECUTOR , kommer de att köras parallellt.

Exempel:

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");
        }
    }
}

Utför Klicka på knappen flera gånger för att starta en uppgift och se resultatet.

Uppgift utförd i trådpool (1)

Varje uppgift tar 1000 ms att slutföra.

Vid t = 36s står uppgifterna 2, 3 och 4 i kö och började köras också för att de körs parallellt.

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) och avdelning Task executed Serially (2).

Utför Klicka på knappen flera gånger för att starta en uppgift och se resultatet.

Den kör serien seriellt, varför varje uppgift startas efter den aktuella utförda uppgiften. Därför när exekvering av uppgift 1 är klar, börjar bara uppgift 2 köras i bakgrunden. Vice versa.

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


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow