Question AsyncTask Exemple Android


Je lisais à propos de AsyncTask, et j'ai essayé le programme simple ci-dessous. Mais cela 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 d'arrière-plan.

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>

561
2018-03-12 17:09


origine


Réponses:


Ok, vous essayez d'accéder à l'interface graphique via un autre thread. Ceci, dans l'ensemble, 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ù vos vues sont.

preExecute() et postExecute() vous offrir l'accès à l'interface graphique 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() pour ensuite montrer les résultats du traitement.

Voyez ces lignes où vous mettez à jour votre TextView plus tard:

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

les mettre PostExecute()

Vous verrez alors votre texte TextView mis à jour après le doInBackground complète.

MODIFIER: J'ai remarqué que votre écouteur onClick ne vérifie pas quelle vue a été sélectionnée. Je trouve que la façon la plus simple de le faire est de passer par des instructions switch. J'ai une classe complète éditée ci-dessous avec toutes les suggestions pour sauver 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) {}
    }
}

613
2018-03-12 17:12



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ù toutes les variables allaient était la partie la plus déroutante au début.

enter image description here


633
2018-04-10 10:41



Je suis sûr qu'il s'exécute correctement, mais vous essayez de modifier les éléments de l'interface utilisateur dans le thread d'arrière-plan et cela ne fonctionnera pas.

Réviser votre appel et AsyncTask comme suit:

Classe d'appel

Remarque: Je suggère personnellement d'utiliser onPostExecute() partout où vous exécutez votre thread AsyncTask et non dans la classe qui étend AsyncTask lui-même. Je pense que cela rend le code plus facile à lire, surtout si vous avez besoin d'AsyncTask à plusieurs endroits pour gérer 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("");

Classe LongThread (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";
}      

66
2018-03-12 17:15



Concept et code ici

J'ai créé un exemple simple pour utiliser AsyncTask d'Android. Ça commence avec onPreExecute(), doInBackground(), publishProgress() et enfin onProgressUpdate().

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

Cependant, si vous devez mettre à jour un widget depuis 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();

Référence de développeur ici


47
2017-09-16 12:02



Déplacez ces deux lignes:

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

sur votre AsyncTask doInBackground méthode et les mettre dans le onPostExecute méthode. Votre AsyncTask devrait ressembler à 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);
    }
}

13
2018-03-12 17:16



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

9
2018-06-12 11:17



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

  1. onPreExecute ()
  2. doInBackground (Params ...)
  3. onProgressUpdate (Progression ...)
  4. onPostExecute (Résultat)

Voici 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 t'aidera...


8
2018-01-23 11:20



Lorsque vous êtes dans le thread de travail, vous ne pouvez pas manipuler directement les éléments de l'interface utilisateur 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;
    }
}

FYI: Pour accéder au thread d'interface utilisateur à partir d'un thread de travail, 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 vous aidera à mieux connaître les choses. Par conséquent, dans votre cas, vous devez définir votre textview dans la méthode onPostExecute ().


5
2017-12-22 18:25



Contexte / Théorie

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

L'utilisateur devrait toujours être en mesure d'interagir avec l'application de sorte qu'il est important éviter de bloquer le thread principal (UI) avec des tâches telles que   télécharger du contenu sur le Web.

C'est pourquoi nous utilisons un AsyncTask.

Il offre une interface simple par l'encapsulation de la file d'attente de messages et du gestionnaire de messages d'interface utilisateur qui vous permettent d'envoyer et de traiter des objets exécutables et des messages provenant d'autres threads.

la mise en oeuvre

AsyncTask est une classe générique. (Ça prend types paramétrés dans son constructeur.)

Il utilise ces trois types génériques: 

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

Progress - le type des unités de progression publiées lors du calcul de l'arrière-plan.

Result - le type du résultat du calcul de l'arrière-plan.

Tous les types ne sont pas toujours utilisés par une tâche asynchrone. Pour marquer un type comme inutilisé, utilisez simplement le type Void:

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

Ces trois paramètres correspondent à trois fonctions principales vous pouvez remplacer dans AsyncTask:

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

Pour exécuter AsyncTask

appel execute() avec les paramètres à envoyer à la tâche d'arrière-plan.

Ce qui se produit

  1. Sur le fil principal / 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.)

    • Où la tâche de longue durée devrait se produire

    • Doit remplacer au moins doInBackground() utiliser AsyncTask.

    • Appel publishProgress(Progress...) mettre à jour un affichage de progression dans l'interface utilisateur pendant que le calcul d'arrière-plan est toujours en cours d'exécution. (Par exemple, animer une barre de progression ou afficher des journaux dans un champ de texte.)

      • Ce qui provoque onProgressUpdate() être appelé.
  3. Sur le thread d'arrière-plan, un résultat est renvoyé doInBackground(). Cela déclenche l'étape suivante.

  4. Sur le fil principal / interface utilisateur, onPostExecute() appelé avec le résultat retourné.

Exemples

En utilisant à nouveau l'exemple de la tâche de blocage consistant à télécharger quelque chose sur le web,

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

Exemple A

le doInBackground() méthode télécharge l'image et la stocke dans un objet de type BitMap. le onPostExecute() méthode 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 d'exécution

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

5
2017-09-17 16:20