Przykład systemu Android AsyncTask


680

Czytałem o tym AsyncTaski wypróbowałem poniższy prosty program. Ale to nie działa. Jak mogę to zrobić?

public class AsyncTaskActivity extends Activity {

    Button btn;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btn = (Button) findViewById(R.id.button1);
        btn.setOnClickListener((OnClickListener) this);
    }

    public void onClick(View view){
        new LongOperation().execute("");
    }

    private class LongOperation extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... params) {
            for(int i=0;i<5;i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("Executed");
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected void onProgressUpdate(Void... values) {
        }
    }
}

Próbuję tylko zmienić etykietę po 5 sekundach w tle.

To jest mój main.xml :

<?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" >
    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:indeterminate="false"
        android:max="10"
        android:padding="10dip">
    </ProgressBar>
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Progress" >
    </Button>
    <TextView android:id="@+id/output"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Replace"/>
</LinearLayout>

1
Możesz także pokazać postęp, wywołując metodę Publprogress () z metody doInBackground ().
osum


oto przykładowy przykład pobierania obrazu: android-ios-tutorials.com/182/...
Houcine

AsyncTask - wzorzec projektu: stackoverflow.com/questions/5058661/…
HenryChuang

3
prosty przykład ... Musisz przeczytać link
c49

Odpowiedzi:


702

Ok, próbujesz uzyskać dostęp do GUI przez inny wątek. Zasadniczo nie jest to dobra praktyka.

AsyncTask wykonuje wszystko doInBackground()wewnątrz innego wątku, który nie ma dostępu do GUI, w którym znajdują się twoje widoki.

preExecute()i postExecute()oferują dostęp do GUI przed i po tym, jak w tym nowym wątku nastąpi duże podnoszenie, a wynik długiej operacji można nawet przekazaćpostExecute() aby następnie wyświetlić wyniki przetwarzania.

Zobacz następujące wiersze, w których później aktualizujesz TextView:

TextView txt = findViewById(R.id.output);
txt.setText("Executed");

Włóż je onPostExecute() .

Zobaczysz wtedy tekst TextView zaktualizowany po doInBackground .

Zauważyłem, że Twój odbiornik onClick nie sprawdza, który widok został wybrany. Uważam, że najłatwiej to zrobić za pomocą instrukcji switch. Mam poniżej pełną klasę ze wszystkimi sugestiami, aby uniknąć zamieszania.

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.System;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.view.View.OnClickListener;

public class AsyncTaskActivity extends Activity implements OnClickListener {

    Button btn;
    AsyncTask<?, ?, ?> runningTask;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = findViewById(R.id.button1);

        // Because we implement OnClickListener, we only
        // have to pass "this" (much easier)
        btn.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        // Detect the view that was "clicked"
        switch (view.getId()) {
        case R.id.button1:
            if (runningTask != null)
                runningTask.cancel(true);
            runningTask = new LongOperation();
            runningTask.execute();
            break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // Cancel running task(s) to avoid memory leaks
        if (runningTask != null)
            runningTask.cancel(true);
    }

    private final class LongOperation extends AsyncTask<Void, Void, String> {

        @Override
        protected String doInBackground(Void... params) {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // We were cancelled; stop sleeping!
                }
            }
            return "Executed";
        }

        @Override
        protected void onPostExecute(String result) {
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("Executed"); // txt.setText(result);
            // You might want to change "executed" for the returned string
            // passed into onPostExecute(), but that is up to you
        }
    }
}

2
Nie mogę tego zrobić <code> btn.setOnClickListener (this); </code> Zaćmienie daje błąd ----- „Metoda setOnClickListener (View.OnClickListener) w typie View nie ma zastosowania do argumentów (AsyncTaskActivity)”
Fox

Radziłbym zmienić ustawienie tekstu tak, aby nie było statyczne, ale weź argument z onPostExecute(String result)metody. Ułatwi to przyszłym czytelnikom, że argument jest wypełniany wartością zwracaną doInBackground(String... params).
Eric

@Eric Tobias - Dokładnie to zrobiono w komentowanej sekcji. W moim pełnym przykładzie śledziłem i odpowiadałem na pytania użytkowników.
Graham Smith

1
Jako dodatek i siewnik Google (i pochodzący od kogoś, kto obecnie uczy się tego, i tak właśnie się z tym spotkałem): większość aktualizacji interfejsu użytkownika, które zrobisz dla czegoś, co wymaga postępów zgłoszonych do użytkownika, jest w oddzwonieniu na ProgressUpdate który jest wykonywany w głównym wątku interfejsu użytkownika.
RichieHH,

1
To z pewnością zepsuje się, jeśli twoja aktywność zostanie z jakiegoś powodu obrócona lub zniszczona ...
Sam

792

Moja pełna odpowiedź jest tutaj , ale tutaj znajduje się objaśniający obraz uzupełniający inne odpowiedzi na tej stronie. Dla mnie zrozumienie, dokąd zmierzają wszystkie zmienne, było najbardziej mylącą częścią na początku.

wprowadź opis zdjęcia tutaj


3
paramsjest tablicą. (W powyższym przykładzie była to Stringtablica). Pozwala to na przekazanie wielu parametrów tego samego typu. Następnie można uzyskać dostęp do tych parametrów, z params[0], params[1], params[2], itd. Na przykład, nie było tylko jedno Stringw paramstablicy. Jeśli chcesz przekazać wiele parametrów różnych typów (na przykład a Stringi an int), zobacz to pytanie .
Suragch

73

Jestem pewien, że działa poprawnie, ale próbujesz zmienić elementy interfejsu w wątku w tle, ale to się nie uda.

Sprawdź swoje połączenie i AsyncTask w następujący sposób:

Klasa wzywająca

Uwaga: Osobiście sugeruję używanie onPostExecute()gdziekolwiek wykonujesz swój wątek AsyncTask, a nie w klasie, która rozszerza sam AsyncTask. Myślę, że dzięki temu kod jest łatwiejszy do odczytania, zwłaszcza jeśli potrzebujesz AsyncTask w wielu miejscach, z nieco innymi wynikami.

new LongThread() {
    @Override public void onPostExecute(String result) {
        TextView txt = (TextView) findViewById(R.id.output);
        txt.setText(result);
    }
}.execute("");

Klasa LongThread (rozszerza AsyncTask):

@Override
protected String doInBackground(String... params) {
    for (int i = 0; i < 5; i++) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    return "Executed";
}      

7
Dziękujemy za podanie przykładu, który oddziela zadanie AsyncTask od działania
sthomps,

1
tak, w końcu ktoś rozdziela zadanie i aktywność. dziękuję. Zastąpienie onPostExecuteaktywności jest genialne.
mcy

58

Pojęcie i kod tutaj

Stworzyłem prosty przykład korzystania z AsyncTask Androida. Zaczyna się od onPreExecute(), doInBackground(), publishProgress()i wreszcie onProgressUpdate().

W tym doInBackground () działa jako wątek tła, podczas gdy inne działają w wątku interfejsu użytkownika. Nie możesz uzyskać dostępu do elementu interfejsu użytkownika w doInBackground (). Sekwencja jest taka sama, jak wspomniałem.

Jednakże, jeśli trzeba zaktualizować dowolny widget z doInBackgroundmożna publishProgressz doInBackgroundktórym będzie zadzwonić onProgressUpdate, aby zaktualizować widget UI.

class TestAsync extends AsyncTask<Void, Integer, String> {
    String TAG = getClass().getSimpleName();

    protected void onPreExecute() {
        super.onPreExecute();
        Log.d(TAG + " PreExceute","On pre Exceute......");
    }

    protected String doInBackground(Void...arg0) {
        Log.d(TAG + " DoINBackGround", "On doInBackground...");

        for (int i=0; i<10; i++){
            Integer in = new Integer(i);
            publishProgress(i);
        }
        return "You are at PostExecute";
    }

    protected void onProgressUpdate(Integer...a) {
        super.onProgressUpdate(a);
        Log.d(TAG + " onProgressUpdate", "You are in progress update ... " + a[0]);
    }

    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        Log.d(TAG + " onPostExecute", "" + result);
    }
}

Nazwij to tak w swojej działalności:

new TestAsync().execute();

Dokumentacja programisty tutaj


3
zajęcia zaczynają się na ogół wielkimi literami w Javie, taki zapis zwykle się stosuje
Vamsi Pavan Mahesh

20

Przenieś te dwie linie:

TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");

z metody AsyncTask doInBackgroundi umieść je w onPostExecutemetodzie. Twój AsyncTaskpowinien wyglądać mniej więcej tak:

private class LongOperation extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... params) {
        try {
            Thread.sleep(5000); // no need for a loop
        } catch (InterruptedException e) {
            Log.e("LongOperation", "Interrupted", e);
            return "Interrupted";
        }
        return "Executed";
    }      

    @Override
    protected void onPostExecute(String result) {               
        TextView txt = (TextView) findViewById(R.id.output);
        txt.setText(result);
    }
}

Hej, co uruchamiam zadanie asynchroniczne w usłudze, chcę zwrócić pewną wartość do głównego wątku interfejsu użytkownika.
Dipen

@Dipen - Sprawdź tę dyskusję . Istnieją dwa problemy: raportowanie wyników z AsyncTask, na które moja odpowiedź odpowiada; i wysyłanie wartości z usługi do wątku interfejsu użytkownika, do którego odnosi się druga dyskusja. Te kwestie są niezależne.
Ted Hopp,

14

Tło / teoria

AsyncTask pozwala uruchomić zadanie w wątku w tle, publikując wyniki w wątku interfejsu użytkownika.

Użytkownik powinien zawsze w stanie współdziałać z aplikacją jest więc ważne , aby uniknąć zablokowania głównego wątku (UI) z zadań, takich jak pobieranie treści z sieci.

Dlatego używamy AsyncTask.

Oferuje prosty interfejs, owijając kolejkę komunikatów wątku interfejsu użytkownika i moduł obsługi, które pozwalają wysyłać i przetwarzać uruchamialne obiekty i komunikaty z innych wątków .

Realizacja

AsyncTask to klasa ogólna. (Wymaga sparametryzowanych typów w swoim konstruktorze).

Wykorzystuje te trzy ogólne typy:

Params - rodzaj parametrów wysyłanych do zadania po wykonaniu.

Progress - rodzaj jednostek postępu opublikowanych podczas obliczeń w tle.

Result - rodzaj wyniku obliczeń w tle.

Nie wszystkie typy są zawsze używane przez zadanie asynchroniczne. Aby oznaczyć typ jako nieużywany, wystarczy użyć typu Pustka:

private class MyTask extends AsyncTask<Void, Void, Void> { ... }

Te trzy parametry odpowiadają trzem podstawowym funkcjom, w których można zastąpić AsyncTask:

  • doInBackground(Params...)
  • onProgressUpdate(Progress...)
  • onPostExecute(Result)

Aby wykonać AsyncTask

  • Wywołanie execute()z parametrami, które zostaną wysłane do zadania w tle.

Co się dzieje

  1. Na głównym wątku / UI , onPreExecute()jest tzw.

    • Aby zainicjować coś w tym wątku. (Np. Pokaż pasek postępu w interfejsie użytkownika.)
  2. W wątku tła , doInBackground(Params...)jest tzw.

    • ( Paramszostały przekazane przezexecute .)
    • Gdzie powinno się zdarzyć długotrwałe zadanie.
    • Musi zastąpić co najmniej, doInBackground()aby użyć AsyncTask.

    • Wywołanie w publishProgress(Progress...)celu zaktualizowania interfejsu użytkownika z wyświetlaniem postępu (np. Animacja interfejsu użytkownika lub wydrukowany tekst dziennika), gdy obliczenia w tle są nadal wykonywane.

      • Powoduje onProgressUpdate()wezwanie.
  3. W wątku tła wynik jest zwracany doInBackground().

    • (To uruchamia następny krok.)
  4. Na głównym wątku / UI , onPostExecute()jest wywoływana z zwróconego wyniku.

Przykłady

W obu przykładach „zadanie blokujące” to pobieranie z Internetu.

  • Przykład A pobiera obraz i wyświetla go w ImageView, natomiast
  • Przykład B pobiera niektóre pliki .

Przykład A

doInBackground()Metoda pobiera obraz i zapisuje go w obiekcie typu bitmapy. onPostExecute()Metoda bierze bitmapę i umieszcza go w ImageView.

class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
    ImageView bitImage;

    public DownloadImageTask(ImageView bitImage) {
        this.bitImage = bitImage;
    }

    protected Bitmap doInBackground(String... urls) {
        String urldisplay = urls[0];
        Bitmap mBmp = null;
        try {
            InputStream in = new java.net.URL(urldisplay).openStream();
            mBmp = BitmapFactory.decodeStream(in);
        } catch (Exception e) {
            Log.e("Error", e.getMessage());
            e.printStackTrace();
        }
        return mBmp;
    }

    protected void onPostExecute(Bitmap result) {
        bitImage.setImageBitmap(result);
    }
}

Przykład B

 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     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));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }

Przykład wykonania B.

new DownloadFilesTask().execute(url1, url2, url3);

Bardzo miło .. Ale ciągle pojawia się błąd dotyczący kolizji typu zwracanego - próbuję użyć niezgodnego typu zwracanego. Próbowałem różnych rodzajów zwrotów, ten sam błąd.
John ktejik

Cześć @johnktejik, możesz poszukać konkretnego problemu. Może tak się dzieje: the-return-type-is-niekompatybilny z asynctask
TT--

1
Świetny! Zastanawiasz się nad edycją ?
Peter Mortensen

12

Po wykonaniu zadania asynchronicznego zadanie przechodzi przez cztery etapy:

  1. onPreExecute ()
  2. doInBackground (Params ...)
  3. onProgressUpdate (Postęp ...)
  4. onPostExecute (wynik)

Poniżej znajduje się przykład demonstracji:

private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {

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

            // Escape early if cancel() is called
            if (isCancelled())
                break;
        }
        return totalSize;
    }

    protected void onProgressUpdate(Integer... progress) {
        setProgressPercent(progress[0]);
    }

    protected void onPostExecute(Long result) {
        showDialog("Downloaded " + result + " bytes");
    }
 }

Po utworzeniu zadanie jest wykonywane bardzo prosto:

new DownloadFilesTask().execute(url1, url2, url3);

execute oczekuje parametru Paremeter jako Runnable. Nie przyjmuje ciągu. Jaki jest twój adres URL? string or not

10

Najkrótszy przykład robienia czegoś asynchronicznie:

class MyAsyncTask extends android.os.AsyncTask {
    @Override
    protected Object doInBackground(Object[] objects) {
        // Do something asynchronously
        return null;
    }
}

Aby uruchomić:

(new MyAsyncTask()).execute();

10

Jak zapamiętać parametry używane w AsyncTask?

Nie rób

Jeśli dopiero zaczynasz korzystać z AsyncTask, często zdarza się, że możesz się pomylić podczas pisania AsyncTask. Głównymi winowajcami są parametry używane w AsyncTask, tj AsyncTask<A, B, C>. W oparciu o podpisy A, B, C (argumenty) metod różnią się, co jeszcze bardziej komplikuje sytuację.

Nie komplikuj!

Kluczem jest nie zapamiętywać . Jeśli potrafisz sobie wyobrazić, co naprawdę musisz zrobić, to napisanie AsyncTask z poprawnym podpisem przy pierwszej próbie byłoby bułką z masłem. Wystarczy dowiedzieć się, co się Input, Progressi Outputto, i będzie dobrze iść.

Czym jest AsyncTask?

AsyncTask to zadanie w tle uruchamiane w wątku w tle. To zajmuje Input, wykonuje Progressi daje Output.

Tj , AsyncTask<Input, Progress, Output>.

Na przykład:

Wpisz opis zdjęcia tutaj

Jaki jest związek z metodami?

Pomiędzy AsyncTaskidoInBackground()

Wpisz opis zdjęcia tutaj

doInBackground()i onPostExecute(),onProgressUpdate () `są również powiązane

Wpisz opis zdjęcia tutaj

Jak napisać to w kodzie?

DownloadTask extends AsyncTask<String, Integer, String>{

    // Always same signature
    @Override
    public void onPreExecute()
    {}

    @Override
    public String doInbackGround(String... parameters)
    {
        // Download code
        int downloadPerc = // Calculate that
        publish(downloadPerc);

        return "Download Success";
    }

    @Override
    public void onPostExecute(String result)
    {
        super.onPostExecute(result);
    }

    @Override
    public void onProgressUpdate(Integer... parameters)
    {
        // Show in spinner, and access UI elements
    }

}

Jak uruchomisz to zadanie?

new DownLoadTask().execute("Paradise.mp3");

6

W wątku roboczym nie można bezpośrednio manipulować elementami interfejsu użytkownika w systemie Android.

Jeśli używasz AsyncTask, zapoznaj się z metodami oddzwaniania.

Na przykład:

public class MyAyncTask extends AsyncTask<Void, Void, Void>{

    @Override
    protected void onPreExecute() {
        // Here you can show progress bar or something on the similar lines.
        // Since you are in a UI thread here.
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);
        // After completing execution of given task, control will return here.
        // Hence if you want to populate UI elements with fetched data, do it here.
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        super.onProgressUpdate(values);
        // You can track you progress update here
    }

    @Override
    protected Void doInBackground(Void... params) {
        // Here you are in the worker thread and you are not allowed to access UI thread from here.
        // Here you can perform network operations or any heavy operations you want.
        return null;
    }
}

FYI: Aby uzyskać dostęp do wątku interfejsu użytkownika z wątku roboczego, możesz albo użyć metody runOnUiThread (), albo metody post w widoku.

Na przykład:

runOnUiThread(new Runnable() {
    textView.setText("something.");
});

or
    yourview.post(new Runnable() {
    yourview.setText("something");
});

Pomoże Ci to lepiej poznać sytuację. Dlatego w twoim przypadku musisz ustawić widok tekstu w metodzie onPostExecute ().



3

Przykładowe zadanie asynchroniczne z żądaniem POST:

List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("key1", "value1"));
params.add(new BasicNameValuePair("key1", "value2"));
new WEBSERVICEREQUESTOR(URL, params).execute();

class WEBSERVICEREQUESTOR extends AsyncTask<String, Integer, String>
{
    String URL;
    List<NameValuePair> parameters;

    private ProgressDialog pDialog;

    public WEBSERVICEREQUESTOR(String url, List<NameValuePair> params)
    {
        this.URL = url;
        this.parameters = params;
    }

    @Override
    protected void onPreExecute()
    {
        pDialog = new ProgressDialog(LoginActivity.this);
        pDialog.setMessage("Processing Request...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(false);
        pDialog.show();
        super.onPreExecute();
    }

    @Override
    protected String doInBackground(String... params)
    {
        try
        {
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpEntity httpEntity = null;
            HttpResponse httpResponse = null;

            HttpPost httpPost = new HttpPost(URL);

            if (parameters != null)
            {
                httpPost.setEntity(new UrlEncodedFormEntity(parameters));
            }
            httpResponse = httpClient.execute(httpPost);

            httpEntity = httpResponse.getEntity();
            return EntityUtils.toString(httpEntity);

        }  catch (Exception e)
        {

        }
        return "";
    }

    @Override
    protected void onPostExecute(String result)
    {
        pDialog.dismiss();

        try
        {

        }
        catch (Exception e)
        {

        }
        super.onPostExecute(result);
    }
}


1

Musisz zadeklarować przycisk onclicklistener. Po kliknięciu wywołuje klasę AsyncTask DownloadJson.

Proces zostanie pokazany poniżej:

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btn = (Button) findViewById(R.id.button1);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new DownloadJson().execute();
            }
        });
    }

    // DownloadJSON AsyncTask
    private class DownloadJson extends AsyncTask<Void, Void, Void> {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Void doInBackground(Void... params) {
            newlist = new ArrayList<HashMap<String, String>>();
            json = jsonParser.makeHttpRequest(json, "POST");
            try {
                newarray = new JSONArray(json);
                    for (int i = 0; i < countdisplay; i++) {
                        HashMap<String, String> eachnew = new HashMap<String, String>();
                        newobject = newarray.getJSONObject(i);
                        eachnew.put("id", newobject.getString("ID"));
                        eachnew.put("name", newobject.getString("Name"));
                        newlist.add(eachnew);
                    }
                }
            } catch (JSONException e) {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void args) {
            newlisttemp.addAll(newlist);
            NewAdapterpager newadapterpager = new NewAdapterpager(ProcesssActivitypager.this, newlisttemp);
            newpager.setAdapter(newadapterpager);
        }
    }

1
private class AsyncTaskDemo extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // Showing progress dialog
        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Loading...");
        progressDialog.setCancelable(false);
        progressDialog.show();
    }

    @Override
    protected Void doInBackground(Void... arg0) {

        // Do code here

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        // Dismiss the progress dialog
        if (progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }

    @Override
    protected void onCancelled() {

        super.onCancelled();
        progressDialog.dismiss();
        Toast toast = Toast.makeText(
                          getActivity(),
                          "An error is occurred due to some problem",
                          Toast.LENGTH_LONG);
        toast.setGravity(Gravity.TOP, 25, 400);
        toast.show();
    }

}


0

Przykładowy przykład AsyncTask z postępem

import android.animation.ObjectAnimator;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

public class AsyncTaskActivity extends AppCompatActivity implements View.OnClickListener {

    Button btn;
    ProgressBar progressBar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button) findViewById(R.id.button1);
        btn.setOnClickListener(this);
        progressBar = (ProgressBar)findViewById(R.id.pbar);
    }

    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.button1:
                new LongOperation().execute("");
                break;
        }
    }

    private class LongOperation extends AsyncTask<String, Integer, String> {

        @Override
        protected String doInBackground(String... params) {
            Log.d("AsyncTask", "doInBackground");
            for (int i = 0; i < 5; i++) {
                try {
                    Log.d("AsyncTask", "task "+(i + 1));
                    publishProgress(i + 1);
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.interrupted();
                }
            }
            return "Completed";
        }

        @Override
        protected void onPostExecute(String result) {
            Log.d("AsyncTask", "onPostExecute");
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText(result);
            progressBar.setProgress(0);
        }

        @Override
        protected void onPreExecute() {
            Log.d("AsyncTask", "onPreExecute");
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("onPreExecute");
            progressBar.setMax(500);
            progressBar.setProgress(0);
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            Log.d("AsyncTask", "onProgressUpdate "+values[0]);
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("onProgressUpdate "+values[0]);

            ObjectAnimator animation = ObjectAnimator.ofInt(progressBar, "progress", 100 * values[0]);
            animation.setDuration(1000);
            animation.setInterpolator(new LinearInterpolator());
            animation.start();
        }
    }
}

0

Zadanie ASync;

public class MainActivity extends AppCompatActivity {

    private String ApiUrl = "your_api";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyTask myTask = new MyTask();
        try {
            String result=myTask.execute(ApiUrl).get();
            Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
           e.printStackTrace();
        }
    }

    public class MyTask extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... strings) {

            String result = "";
            HttpURLConnection httpURLConnection = null;
            URL url;

            try {
                url = new URL(strings[0]);
                httpURLConnection = (HttpURLConnection) url.openConnection();
                InputStream inputStream = httpURLConnection.getInputStream();
                InputStreamReader reader = new InputStreamReader(inputStream);
                result = getData(reader);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return result;
        }

        public String getData(InputStreamReader reader) throws IOException {

            String result = "";
            int data = reader.read();
            while (data!=-1) {
                char now = (char) data;
                result += data;
                data = reader.read();
            }
            return result;
        }
    }

}

Dlaczego klasa jest MyTaskw klasie MainActivity? Czy to jest zwyczajowe?
Peter Mortensen,

0

Podczas pracy z AsyncTask konieczne jest utworzenie następcy klasy i zarejestrowanie w nim implementacji niezbędnych dla nas metod. W tej lekcji przyjrzymy się trzem metodom:

doInBackground - zostanie wykonany w nowym wątku, a tutaj rozwiązujemy wszystkie nasze trudne zadania. Ponieważ wątek inny niż podstawowy nie ma dostępu do interfejsu użytkownika.

onPreExecute - wykonywany przed doInBackground i ma dostęp do interfejsu użytkownika

onPostExecute - wykonywany po doInBackground (nie działa, jeśli AsyncTask został anulowany - o tym w następnych lekcjach) i ma dostęp do interfejsu użytkownika.

To jest klasa MyAsyncTask:

class MyAsyncTask extends AsyncTask<Void, Void, Void> {

  @Override
  protected void onPreExecute() {
    super.onPreExecute();
    tvInfo.setText("Start");
  }

  @Override
  protected Void doInBackground(Void... params) {
    // Your background method
    return null;
  }

  @Override
  protected void onPostExecute(Void result) {
    super.onPostExecute(result);
    tvInfo.setText("Finish");
  }
}

Oto jak wywołać swoją Aktywność lub Fragment:

MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute();

Re „o tym w następnych lekcjach” : Co to dotyczy? Np. Skąd to się bierze?
Peter Mortensen,

0

jeśli otworzysz klasę AsyncTask, zobaczysz poniższy kod.

public abstract class AsyncTask<Params, Progress, Result> {
    @WorkerThread
    protected abstract Result doInBackground(Params... params);
    @MainThread
    protected void onPreExecute() {
    }
    @SuppressWarnings({"UnusedDeclaration"})
    @MainThread
    protected void onPostExecute(Result result) {
    }
}

Funkcje AsyncTask

  1. AsyncTask to klasa abstrakcyjna
  2. AsyncTask ma 3 ogólne parametry.
  3. AsyncTask ma abstrakcyjną metodę doInBackground, onPreExecute, onPostExecute
  4. doInBackground to WorkerThread (nie można zaktualizować interfejsu użytkownika)
  5. onPreExecute jest MainThread
  6. onPostExecute to MainThread (możesz zaktualizować interfejs użytkownika)

przykład

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    mEmailView = (AutoCompleteTextView) findViewById(R.id.email);

    AsyncTask<Void, Void, Post> asyncTask = new AsyncTask<Void, Void, Post>() {
        @Override
        protected Post doInBackground(Void... params) {
            try {
                ApiClient defaultClient = Configuration.getDefaultApiClient();
                String authorization = "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1ODIxMzM4MTB9.bA3Byc_SuB6jzqUGAY4Pyt4oBNg0VfDRctZ8-PcPlYg"; // String | JWT token for Authorization
                ApiKeyAuth Bearer = (ApiKeyAuth) defaultClient.getAuthentication("Bearer");
                Bearer.setApiKey(authorization);
                PostApi apiInstance = new PostApi();
                String id = "1"; // String | id
                Integer commentPage = 1; // Integer | Page number for Comment
                Integer commentPer = 10; // Integer | Per page number For Comment
                Post result;
                try {
                    result = apiInstance.apiV1PostsIdGet(id, authorization, commentPage, commentPer);
                } catch (ApiException e) {
                    e.printStackTrace();
                    result = new Post();
                }
                return result;
            } catch (Exception e) {
                e.printStackTrace();
                return new Post();
            }
        }

        @Override
        protected void onPostExecute(Post post) {
            super.onPostExecute(post);
            if (post != null) {
                mEmailView.setText(post.getBody());
                System.out.print(post);
            }
        }
    };
    asyncTask.execute();
}

-1

Zmień kod, jak podano poniżej:

@Override
protected void onPostExecute(String result) {

    runOnUiThread(new Runnable() {
        public void run() {
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("Executed");
        }
    });
}

1
Nie powinieneś używać runOnUiThread, ponieważ onPostExecute zawsze działa na wątku 1 (prawda?)
justdan0227 16.07.16
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.