Exemple AsyncTask Android

je lisais à propos de AsyncTask , et j'ai essayé le programme simple ci-dessous. Mais il ne semble pas fonctionner. Comment puis-je le faire fonctionner?

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) {
        }
    }
}

j'essaie juste de changer l'étiquette après 5 secondes dans le processus de fond.

c'est mon 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>
581
demandé sur Igor Tyulkanov 2012-03-12 21:09:39

15 réponses

Ok vous essayez d'accéder à l'interface graphique via un autre thread. Ceci, pour l'essentiel, n'est pas une bonne pratique.

l'AsyncTask exécute tout dans doInBackground() à l'intérieur d'un autre thread, qui n'a pas accès à l'interface graphique où se trouvent vos vues.

preExecute() et postExecute() vous offrent l'accès à GUI avant et après le levage lourd se produit dans ce nouveau fil, vous pouvez même passer le résultat de la longue opération à postExecute() à puis afficher les résultats du traitement.

voyez ces lignes où vous mettez à jour votre TextView:

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

mettez-les dans PostExecute()

vous verrez alors votre texte TextView mis à jour après la fin de doInBackground .

EDIT: j'ai remarqué que votre onClick auditeur ne vérifie pas la Vue qui a été sélectionné. Je trouve que la façon la plus facile de le faire est via switch déclaration. J'ai une classe complète éditée ci-dessous avec toutes les suggestions pour éviter la confusion.

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
répondu Graham Smith 2015-08-07 09:21:35

ma réponse complète est ici , Mais voici une image explicative pour compléter les autres réponses sur cette page. Pour moi, comprendre où allaient toutes les variables a été la partie la plus déroutante au début.

enter image description here

652
répondu Suragch 2017-05-23 12:10:34

je suis sûr que l'exécution est correcte, mais vous essayez de changer les éléments de L'interface utilisateur dans le thread d'arrière-plan et ça ne va pas.

réviser votre appel et AsyncTask comme suit:

L'Appel De La Classe

Note: personnellement, je suggère d'utiliser onPostExecute() partout où vous exécutez votre thread AsyncTask et non dans la classe qui s'étend à AsyncTask lui-même. Je pense que ça fait le code plus facile à lire surtout si vous avez besoin de L'AsyncTask en plusieurs endroits manipulant les résultats légèrement différents.

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

LongThread class (extends 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
répondu bbedward 2016-06-30 04:40:07

Concept et code ici

j'ai créé un exemple simple pour utiliser AsyncTask D'Android. Il commence par onPreExecute(), doInBackground(), publishProgress() et finalement onProgressUpdate() .

dans ce doInBackground() fonctionne comme un thread d'arrière-plan, tandis que d'autres travaux dans le Thread D'UI. Vous ne pouvez pas accéder à un élément UI dans doInBackground(). La séquence est la même que j'ai mentionné.

cependant si vous besoin de mettre à jour n'importe quel widget de doInBackground vous pouvez publishProgress de doInBackground qui appellera onProgressUpdate pour mettre à jour votre 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);
    }
}

appelez ça comme ça dans votre activité:

new TestAsync().execute();

De Référence Du Développeur Ici

49
répondu nitesh 2017-04-25 09:37:23

déplacer ces deux lignes:

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

de votre méthode AsyncTask doInBackground et mettez-les dans la méthode onPostExecute . Votre AsyncTask devrait ressembler à quelque chose comme ceci:

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
répondu Ted Hopp 2012-03-12 17:16:50

exemple le plus court pour faire quelque chose de manière asynchrone:

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

pour l'exécuter:

(new MyAsyncTask()).execute();
10
répondu WhereDatApp.com 2014-06-12 11:17:03

Quand une tâche asynchrone est exécutée, la tâche passe par 4 étapes:

  1. onPreExecute ()
  2. doInBackground (Params...)
  3. onProgressUpdate (Progress...)
  4. onPostExecute (résultat)

ci-dessous est un exemple de démonstration

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

et une fois que vous avez créé, une tâche est exécutée très simplement:

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

J'espère que cela va vous aider...

9
répondu Ganesh Katikar 2014-01-23 11:20:21

Arrière-Plan De La Théorie

AsyncTask vous permet d'exécuter une tâche sur un thread d'arrière-plan, tout en publiant les résultats sur le thread de L'interface utilisateur.

L'utilisateur doit toujours capable d'interagir avec l'application, de sorte qu'il est important pour éviter de bloquer le fil principal (UI) avec des tâches telles que: le téléchargement de contenu à partir du web.

C'est pourquoi nous utilisons un AsyncTask .

il offre une interface simple par enveloppant la queue de message de thread D'UI et handler qui vous permettent d'envoyer et de traiter des objets et des messages runnables à partir d'autres threads .

mise en œuvre

AsyncTask est une classe générique. (Il faut des types paramétrisés dans son constructeur.)

il utilise ces trois types génériques:

Params - le type de paramètres envoyés à la tâche lors de l'exécution.

Progress - le type des unités de progrès publiées pendant le calcul de l'arrière-plan.

Result - le type de le résultat du calcul de fond.

tous les types ne sont pas toujours utilisés par une tâche asynchrone. Pour marquer un type comme non utilisé, il suffit d'utiliser le type Void:

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

ces trois paramètres correspondent à trois fonctions principales vous pouvez outrepasser en AsyncTask :

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

pour exécuter AsyncTask

call execute() avec paramètres à envoyer à la tâche de fond.

Ce Qui Arrive

  1. À la main/thread d'INTERFACE utilisateur, onPreExecute() est appelé. (Pour initialiser quelque chose dans ce fil, comme afficher une barre de progression sur l'interface utilisateur.)

  2. sur un fil de fond, doInBackground(Params...) est appelé. (Les paramètres sont ceux passés à la fonction Execute.)

    • "là où la tâche de longue durée devrait se produire

    • doit remplacer au moins doInBackground() pour utiliser AsyncTask.

    • Call publishProgress(Progress...) " pour mettre à jour un affichage de progrès dans l'interface utilisateur pendant que le calcul d'arrière-plan est encore en cours d'exécution. (par exemple animer une barre de progression ou afficher les journaux dans un champ de texte.)

      • cette cause onProgressUpdate() pour être appelé.
  3. On le fil de fond, un résultat est retourné de doInBackground() . Cela déclenche l'étape suivante.

  4. À la main/thread d'INTERFACE utilisateur, onPostExecute() appelée avec le résultat retourné.

Exemples

en Utilisant à nouveau l'exemple du blocage, de la tâche à télécharger quelque chose sur le web,

  • Exemple A télécharge une image et l'affiche dans une ImageView,
  • tandis que exemple B télécharge des fichiers .

Exemple A

la méthode doInBackground() télécharge l'image et la stocke dans un objet de type BitMap. La méthode onPostExecute() prend le bitmap et le place dans L'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);
    }
}

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

exemple B exécution

new DownloadFilesTask().execute(url1, url2, url3);
7
répondu TT-- 2018-07-10 18:34:55

lorsque vous êtes dans le thread worker, vous ne pouvez pas manipuler directement les éléments UI sur Android.

lorsque vous utilisez AsyncTask, veuillez comprendre les méthodes de rappel.

par exemple:

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

pour information: Pour accéder au fil UI à partir d'un fil worker, vous utilisez la méthode runOnUiThread() ou la méthode post sur votre vue.

par exemple:

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

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

cela aidera tu connais mieux les choses. Par conséquent, dans votre cas, vous devez configurer votre textview dans la méthode onPostExecute ().

6
répondu Krishna 2016-06-22 19:53:25

je vous recommande de rendre votre vie plus facile en utilisant cette bibliothèque pour les travaux de fond https://github.com/Arasthel/AsyncJobLibrary

c'est simple..

AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() {

    @Override
    public void doOnBackground() {
        startRecording();
    }
});
4
répondu kc ochibili 2014-11-29 23:39:17

exemple de tâche Async avec POST request:

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
répondu user1728578 2016-06-22 19:49:01

vous devez déclarer le bouton onclicklistener, une fois qu'il appelle AsyncTask Class DownloadJson, le processus sera montré ci-dessous:

@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
répondu Cristiana Chavez 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
répondu Vaishali Sutariya 2014-08-26 04:12:11

simplement:

LongOperation MyTask = new LongOperation();
MyTask.execute();
1
répondu Ebin Sebastian 2016-06-22 19:47:06

changer votre code comme indiqué ci-dessous:

@Override
protected void onPostExecute(String result) {

    runOnUiThread(new Runnable() {
        public void run() {
            TextView txt = (TextView) findViewById(R.id.output);
            txt.setText("Executed");
        }
    });
}
0
répondu Biswajit Karmakar 2016-06-22 19:54:57