Przykład AsyncTask Android

Czytałem o AsyncTask i wypróbowałem prosty program poniżej. Ale to chyba nie działa. Jak mogę to zrobić?

package com.test;

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 {
    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ę zmienić etykietę po 5 sekundach w tle.

To mój Główny.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>
Author: Igor Tyulkanov, 2012-03-12

15 answers

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

AsyncTask wykonuje wszystko w 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 ciężkich podnoszenia występuje w tym nowym wątku, można nawet przekazać wynik długiej operacji do postExecute(), aby następnie pokazać wszelkie wyniki przetwarzania.

Zobacz te linie, gdzie jesteś późniejsza aktualizacja widoku tekstowego:

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

Włóż je do PostExecute()

Tekst TextView zostanie zaktualizowany po zakończeniu doInBackground.

EDIT: zauważyłem, że Twój słuchacz onClick nie sprawdza, który Widok został wybrany. Najłatwiej jest to zrobić za pomocą instrukcji switch. Mam pełną klasę edytowane poniżej ze wszystkimi sugestiami, aby zaoszczędzić 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;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = (Button) findViewById(R.id.button1);
        // because we implement OnClickListener we only have to pass "this"
        // (much easier)
        btn.setOnClickListener(this);
    }

    public void onClick(View view) {
        // detect the view that was "clicked"
        switch (view.getId()) {
        case R.id.button1:
            new LongOperation().execute("");
            break;
        }
    }

    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) {
                    Thread.interrupted();
                }
            }
            return "Executed";
        }

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

        @Override
        protected void onPreExecute() {}

        @Override
        protected void onProgressUpdate(Void... values) {}
    }
}
 626
Author: Graham Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-07 09:21:35

Moja pełna odpowiedź jest tutaj , ale tutaj jest obrazek wyjaśniający, aby uzupełnić inne odpowiedzi na tej stronie. Dla mnie zrozumienie, dokąd zmierzają wszystkie zmienne, było najbardziej mylące na początku.

Tutaj wpisz opis obrazka

 652
Author: Suragch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:34

Jestem pewien, że działa poprawnie, ale próbujesz zmienić elementy interfejsu w wątku tła, a to nie wystarczy.

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

Wywołanie Klasy

Uwaga: osobiście sugeruję użycie onPostExecute() wszędzie tam, gdzie wykonujesz swój wątek AsyncTask, a nie w klasie, która rozszerza samą AsyncTask. Myślę, że to sprawia, że kod jest łatwiejszy do odczytania, zwłaszcza jeśli potrzebujesz AsyncTask w wielu miejscach obsługi wyników trochę inaczej.

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";
}      
 67
Author: bbedward,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-30 04:40:07

Koncepcja i Kod tutaj

Stworzyłem prosty przykład użycia AsyncTask Androida. Zaczyna się od onPreExecute(), doInBackground(), publishProgress() i na końcu onProgressUpdate().

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

Jeśli jednak chcesz zaktualizować dowolny widget z doInBackground, możesz publishProgress z doInBackground, który wywoła onProgressUpdate, aby zaktualizować interfejs użytkownika widget.

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 aktywności:

new TestAsync().execute();

Odnośnik Programisty Tutaj

 49
Author: nitesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-25 09:37:23

Przesuń te dwie linie:

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

Z metody AsyncTask doInBackground i umieścić je w metodzie onPostExecute. Twój AsyncTask powinien 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);
    }
}
 15
Author: Ted Hopp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-12 17:16:50

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 go uruchomić:

(new MyAsyncTask()).execute();
 10
Author: WhereDatApp.com,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-12 11:17:03

Gdy wykonywane jest zadanie asynchroniczne, zadanie przechodzi przez 4 etapy:

  1. onPreExecute ()
  2. doInBackground(Params...)
  3. onProgressUpdate (Progress...)
  4. onPostExecute (Result)

Poniżej znajduje się przykład demo

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

I po utworzeniu, zadanie jest wykonywane bardzo prosto:

 new DownloadFilesTask().execute(url1, url2, url3);
Mam nadzieję, że to ci pomoże...
 9
Author: Ganesh Katikar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-23 11:20:21

Tło / Teoria

AsyncTask pozwala na uruchomienie zadania w wątku tła, podczas publikowania wyników w wątku interfejsu użytkownika.

Użytkownik powinien zawsze mieć możliwość interakcji z aplikacją, więc jest to ważne]} aby uniknąć blokowania głównego (UI) wątku z zadaniami takimi jak pobieranie treści z sieci.

Dlatego używamy AsyncTask.

Oferuje prosty interfejs przez owijanie kolejki wiadomości wątku interfejsu użytkownika i obsługi, która pozwala na wysyłanie i przetwarzanie uruchomionych obiektów i wiadomości z innych wątków.

Realizacja

AsyncTask jest klasą generyczną. (Przyjmuje typy parametryzowane w swoim konstruktorze.)

Używa tych trzech rodzajów generycznych:

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

Progress - Typ jednostek postępu opublikowanych podczas obliczeń tła.

Result - Typ wyniku obliczeń tła.

Nie wszystkie typy są zawsze używane przez zadanie asynchroniczne. Aby oznaczyć Typ jako nieużywany, po prostu użyj typu Void:

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

Te trzy parametry odpowiadają trzem podstawowym funkcjom można nadpisać w AsyncTask:

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

Aby wykonać AsyncTask

Call execute() z parametrami do wysłania do zadania w tle.

Co Się Dzieje

  1. Na wątku main / UI, onPreExecute() nazywa się. (Aby zainicjować coś w tym wątku, na przykład pokazać pasek postępu w interfejsie użytkownika.)

  2. Na wątku tła, doInBackground(Params...) na dzwoniłem. (Parametry są przekazywane do funkcji Execute.)

    • Gdzie powinno nastąpić zadanie długotrwałe

    • Aby użyć AsyncTask, musi nadpisać co najmniej doInBackground().

    • Call publishProgress(Progress...) aby zaktualizować wyświetlanie postępu w interfejsie użytkownika podczas wykonywania obliczeń w tle. (np. Animuj pasek postępu lub pokaż dzienniki w polu tekstowym.)

      • to powoduje onProgressUpdate() być dzwoniłem.
  3. W wątku tła zwracany jest wynik doInBackground(). To uruchamia następny krok.

  4. Na wątku main / UI, onPostExecute() wywołane z zwróconym wynikiem.

Przykłady

Na przykład blokowanie zadania polega na pobraniu czegoś z sieci.]}
  • Przykład A pobiera obraz i wyświetla go w widoku ImageView,
  • while przykład B pobiera niektóre pliki .

Przykład A

Metoda doInBackground() pobiera obraz i przechowuje go w obiekcie typu BitMap. Metoda onPostExecute() pobiera bitmapę i umieszcza ją w widoku 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 B wykonanie

new DownloadFilesTask().execute(url1, url2, url3);
 7
Author: TT--,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-10 18:34:55

Gdy jesteś w wątku roboczym, nie możesz bezpośrednio manipulować elementami interfejsu użytkownika na Androidzie.

Podczas korzystania z AsyncTask proszę zrozumieć metody wywołania zwrotnego.

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, należy użyć metody runOnUiThread () lub metody post w widoku.

Na przykład:

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

or
    yourview.post(new Runnable() {
    yourview.setText("something");
});
To pomoże Ci lepiej poznać rzeczy. Dlatego w Twoim przypadku musisz ustawić textview w onPostExecute() metoda.
 6
Author: Krishna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 19:53:25

Polecam ułatwić sobie życie, używając tej biblioteki do prac w tle https://github.com/Arasthel/AsyncJobLibrary

To takie proste..
AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() {

    @Override
    public void doOnBackground() {
        startRecording();
    }
});
 4
Author: kc ochibili,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-29 23:39:17

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);
    }
}
 3
Author: user1728578,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 19:49:01

Musisz zadeklarować przycisk onclicklistener, po kliknięciu wywoła AsyncTask class 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
Author: Cristiana Chavez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-25 04:35:45
 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(),
                "Error is occured due to some probelm", Toast.LENGTH_LONG);
        toast.setGravity(Gravity.TOP, 25, 400);
        toast.show();

    }

}
 1
Author: Vaishali Sutariya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-26 04:12:11

Po Prostu:

LongOperation MyTask = new LongOperation();
MyTask.execute();
 1
Author: Ebin Sebastian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 19:47:06

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");
        }
    });
}
 0
Author: Biswajit Karmakar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-22 19:54:57