148 votes

Android asynctask envoyant des callbacks à l'ui

J'ai la classe asynctask suivante qui n'est pas dans l'activité. Dans l'activité, j'initialise l'asynctask, et je veux que l'asynctask rapporte les callbacks à mon activité. Est-ce possible ? Ou est-ce que l'asynctask doit être dans le même fichier de classe que l'activité ?

protected void onProgressUpdate(Integer... values) 
{
    super.onProgressUpdate(values);
    caller.sometextfield.setText("bla");
}

Quelque chose comme ça ?

395voto

Dmitry Zaitsev Points 7119

Vous pouvez créer un interface et le passe à AsyncTask (dans le constructeur), et ensuite appeler la méthode dans onPostExecute()

Par exemple :

Votre interface :

public interface OnTaskCompleted{
    void onTaskCompleted();
}

Votre activité :

public class YourActivity implements OnTaskCompleted{
    // your Activity
}

Et votre AsyncTask :

public class YourTask extends AsyncTask<Object,Object,Object>{ //change Object to required type
    private OnTaskCompleted listener;

    public YourTask(OnTaskCompleted listener){
        this.listener=listener;
    }

    // required methods

    protected void onPostExecute(Object o){
        // your stuff
        listener.onTaskCompleted();
    }
}

EDITAR

Comme cette réponse a été très populaire, je veux ajouter quelques éléments.

Si vous êtes novice en matière de développement Android, AsyncTask est un moyen rapide de faire fonctionner les choses sans bloquer le thread de l'interface utilisateur. Elle résout effectivement certains problèmes, il n'y a rien de mal à ce que la classe fonctionne elle-même. Cependant, elle apporte quelques implications, telles que :

  • Possibilité de fuites de mémoire. Si vous gardez une référence à votre Activity il restera en mémoire même après que l'utilisateur a quitté l'écran (ou fait tourner l'appareil).
  • AsyncTask ne donne pas de résultat à Activity si Activity a déjà été détruite. Il faut ajouter du code supplémentaire pour gérer tout ça ou faire deux fois les opérations.
  • Un code compliqué qui fait tout en Activity

Lorsque vous estimez que vous avez suffisamment mûri pour passer à autre chose avec Android, jetez un coup d'œil à cet article ce qui, à mon avis, est une meilleure solution pour développer vos applications Android avec des opérations asynchrones.

47voto

Arshad Points 704

Je pense que l'approche ci-dessous est très facile.

J'ai déclaré une interface pour le callback

public interface AsyncResponse {
    void processFinish(Object output);
}

Puis création d'une tâche asynchrone pour répondre à tous les types de demandes parallèles.

 public class MyAsyncTask extends AsyncTask<Object, Object, Object> {

    public AsyncResponse delegate = null;//Call back interface

    public MyAsyncTask(AsyncResponse asyncResponse) {
        delegate = asyncResponse;//Assigning call back interfacethrough constructor
    }

    @Override
    protected Object doInBackground(Object... params) {

    //My Background tasks are written here

      return {resutl Object}

    }

    @Override
    protected void onPostExecute(Object result) {
        delegate.processFinish(result);
    }

}

Ensuite, appelez la tâche asynchrone lorsque vous cliquez sur un bouton dans l'activité Class.

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {

        Button mbtnPress = (Button) findViewById(R.id.btnPress);

        mbtnPress.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                MyAsyncTask asyncTask =new MyAsyncTask(new AsyncResponse() {

                    @Override
                    public void processFinish(Object output) {
                        Log.d("Response From Asynchronous task:", (String) output);          
                        mbtnPress.setText((String) output);
                    }
                });
                asyncTask.execute(new Object[] { "Youe request to aynchronous task class is giving here.." });

            }
        });
    }
}

Gracias

6voto

Miguel Points 406

En complément des réponses ci-dessus, vous pouvez également personnaliser vos fallbacks pour chaque appel asynchrone que vous faites, de sorte que chaque appel à la méthode générique ASYNC remplira des données différentes, en fonction de l'élément onTaskDone que vous y avez placé.

  Main.FragmentCallback FC= new  Main.FragmentCallback(){
            @Override
            public void onTaskDone(String results) {

                localText.setText(results); //example TextView
            }
        };

new API_CALL(this.getApplicationContext(), "GET",FC).execute("&Books=" + Main.Books + "&args=" + profile_id);

Rappelez-vous : J'ai utilisé l'interface sur l'activité principale, c'est là que vient le mot "principal", comme ceci :

public interface FragmentCallback {
    public void onTaskDone(String results);

}

Mon API post execute ressemble à ceci :

  @Override
    protected void onPostExecute(String results) {

        Log.i("TASK Result", results);
        mFragmentCallback.onTaskDone(results);

    }

Le constructeur de l'API ressemble à ceci :

 class  API_CALL extends AsyncTask<String,Void,String>  {

    private Main.FragmentCallback mFragmentCallback;
    private Context act;
    private String method;

    public API_CALL(Context ctx, String api_method,Main.FragmentCallback fragmentCallback) {
        act=ctx;
        method=api_method;
        mFragmentCallback = fragmentCallback;

    }

2voto

ichalos Points 41

Je vais répéter ce que les autres ont dit, mais en essayant de faire plus simple...

Tout d'abord, il suffit de créer la classe d'interface

public interface PostTaskListener<K> {
    // K is the type of the result object of the async task 
    void onPostTask(K result);
}

Ensuite, créez l'AsyncTask (qui peut être une classe statique interne de votre activité ou fragment) qui utilise l'interface, en incluant une classe concrète. Dans l'exemple, le PostTaskListener est paramétré avec String, ce qui signifie qu'il attend une classe String comme résultat de la tâche asynchrone.

public static class LoadData extends AsyncTask<Void, Void, String> {

    private PostTaskListener<String> postTaskListener;

    protected LoadData(PostTaskListener<String> postTaskListener){
        this.postTaskListener = postTaskListener;
    }

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

        if (result != null && postTaskListener != null)
            postTaskListener.onPostTask(result);
    }
}

Enfin, la partie où vous combinez votre logique. Dans votre activité / fragment, créez le PostTaskListener et passez-le à la tâche asynchrone. Voici un exemple :

...
PostTaskListener<String> postTaskListener = new PostTaskListener<String>() {
    @Override
    public void onPostTask(String result) {
        //Your post execution task code
    }
}

// Create the async task and pass it the post task listener.
new LoadData(postTaskListener);

C'est fait !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X