web-dev-qa-db-fra.com

Classe commune pour AsyncTask dans Android?

J'ai une classe commune, par exemple pour la classe A qui étend AsyncTask et a toutes les méthodes implémentées, c'est-à-dire onPreExecute, doinbackground et onPostExecute.

Maintenant, il existe d'autres classes qui souhaitent utiliser un objet de classe A.

Supposons que la classe B utilise la classe A de la manière suivante

A a = new A(context)
a.execute(url)

Ensuite, je récupère le résultat dans la méthode get. Mais la méthode get n'est pas la bonne façon d'utiliser AsyncTask. Je voudrais obtenir le résultat dans onPostExecute. Pour cela, j'ai essayé d'utiliser un paramètre booléen qui ne deviendra vrai que dans onpostexecute. La classe B vérifiera jusqu'à ce qu'elle devienne vraie et quand elle deviendra vraie, elle récupérera le résultat.

Mais cela bloque en quelque sorte l'application.

J'ai placé le code pour asynctask ci-dessous.

"

import Java.io.IOException;

import org.Apache.http.client.ClientProtocolException;

import org.Apache.http.client.HttpClient;

import org.Apache.http.client.ResponseHandler;

import org.Apache.http.client.methods.HttpGet;

import org.Apache.http.impl.client.BasicResponseHandler;

import org.Apache.http.impl.client.DefaultHttpClient;


import Android.app.ProgressDialog;
import Android.content.Context;
import Android.os.AsyncTask;

public class A extends AsyncTask<String, Void, String> 
{
private Context context = null;

private final HttpClient httpClient = new DefaultHttpClient();

private String content = null;
//private String error = null;
private String finalResult = null;
private static boolean isResult = false;

private ProgressDialog progressDialog = null; 

public BabbleVilleSyncTask(Context context)
{
    this.context = context; 
    progressDialog = new ProgressDialog(this.context);
}

protected void onPreExecute() 
{
    progressDialog.setMessage("Please Wait....");
    progressDialog.show();
}

protected String doInBackground(String... urls) 
{
    try 
    {
        //urls[0] = URLEncoder.encode(urls[0], "UTF-8");

        HttpGet httpget = new HttpGet(urls[0]);
        ResponseHandler<String> responseHandler = new BasicResponseHandler();
        content = httpClient.execute(httpget, responseHandler);
    }
    /*catch(UnsupportedEncodingException ue)
    {
        error = ue.getMessage();
    }*/
    catch (ClientProtocolException e) 
    {
        //error = e.getMessage();
        cancel(true);
    }
    catch (IOException e) 
    {
        //error = e.getMessage();
        cancel(true);
    }

    httpClient.getConnectionManager().shutdown();

    return content;
}

protected void onPostExecute(String result) 
{
    finalResult = result;
    progressDialog.dismiss();
    System.out.println("on Post execute called");
    isResult = true;
}  

public boolean getIsResult()
{
    return isResult;
}

public void setIsResult(boolean flag)
{
    isResult = flag;
}

public String getResult()
{
    return finalResult;
}
}

"

Quelqu'un peut-il me faire savoir quel est le problème?

Cordialement

Sunil

38
sunil

Une façon propre d'utiliser AsyncTask pour obtenir un résultat serait d'utiliser une interface de rappel.

Voici un exemple simple de ce concept:

interface AsyncTaskCompleteListener<T> {
   public void onTaskComplete(T result);
}

puis dans votre classe B:

class B implements AsyncTaskCompleteListener<String> {

    public void onTaskComplete(String result) {
        // do whatever you need
    }

    public void launchTask(String url) {
        A a = new A(context, this);
        a.execute(url);
    }
}

vous devez maintenant ajouter le code suivant à votre classe A:

class A extends AsyncTask<String, Void, String> {
    private AsyncTaskCompleteListener<String> callback;

    public A(Context context, AsyncTaskCompleteListener<String> cb) {
        this.context = context;
        this.callback = cb;
    }

    protected void onPostExecute(String result) {
       finalResult = result;
       progressDialog.dismiss();
       System.out.println("on Post execute called");
       callback.onTaskComplete(result);
   }  
}

De cette façon, vous n'avez pas besoin d'attendre explicitement que votre tâche se termine, à la place, votre code principal (qui est probablement le thread d'interface utilisateur principal), attend dans la boucle d'événement normale Android, et la méthode onTaskComplete sera automatiquement appelée, permettant de gérer le résultat de la tâche là-bas.

136
SirDarius
public abstract class BaseTask<T> extends AsyncTask<Object, Void, T> {

    public Context context;
    public ProgressDialog dialog;
    public Exception exception;

    protected BaseTask() {
    }

    public BaseTask(Context context) {
        this.context = context;
        this.dialog = new ProgressDialog(context);
    }

    @Override
    protected void onPreExecute() {
        this.dialog.setMessage(context.getResources().getString(R.string.loading));
        this.dialog.show();
    }

    @Override
    protected T doInBackground(Object... objects) {
        try {
           return doWork(objects);
        } catch (Exception e) {
            exception = e;
        }
        return null;
    }

    @Override
    protected void onPostExecute(T result) {
        if (dialog.isShowing()) dialog.dismiss();
        if (exception == null) {
            onResult(result);
        } else {
           onError();
        }
    }



    public abstract T doWork(Object... objects) throws Exception;
    public abstract void onResult(T result);
    public abstract void onError();



}
6
Georgy Gobozov

Je ferais de la classe A une classe privée intégrée à la classe parent, et une fois le travail terminé, elle devrait mettre à jour les propriétés de la classe parent, c'est possible sur PostExecute.

1
Pentium10