web-dev-qa-db-fra.com

Passer des arguments à AsyncTask et renvoyer des résultats

J'ai une application qui fait de longs calculs, et je voudrais afficher une boîte de dialogue de progression pendant que cela est fait. Jusqu'à présent, j'ai découvert que je pouvais le faire avec des threads/gestionnaires, mais cela ne fonctionnait pas, puis j'ai découvert le AsyncTask.

Dans mon application, j'utilise des cartes avec des marqueurs dessus, et j'ai implémenté la fonction onTap pour appeler une méthode que j'ai définie. La méthode crée une boîte de dialogue avec des boutons Oui/Non, et je voudrais appeler un AsyncTask si Oui est cliqué. Ma question est de savoir comment passer un ArrayList<String> au AsyncTask (et travailler avec lui là-bas), et comment récupérer un nouveau ArrayList<String> comme un résultat du AsyncTask?

Le code de la méthode ressemble à ceci:

String curloc = current.toString();
String itemdesc = item.mDescription;

ArrayList<String> passing = new ArrayList<String>();
passing.add(itemdesc);
passing.add(curloc);

ArrayList<String> result = new ArrayList<String>();

new calc_stanica().execute(passing,result);

String minim = result.get(0);
int min = Integer.parseInt(minim);

String glons = result.get(1);
String glats = result.get(2);

double glon = Double.parseDouble(glons);
double glat = Double.parseDouble(glats);

GeoPoint g = new GeoPoint(glon, glat);
String korisni_linii = result.get(3);

Donc, comme vous le voyez, je voudrais envoyer la liste de tableaux de chaînes "en passant" à AsyncTask, et en récupérer la liste de tableaux de chaînes "résultat". Et la classe calc_stanica AssycTask ressemble à ceci:

public class calc_stanica extends AsyncTask<ArrayList<String>, Void, ArrayList<String>> {
    ProgressDialog dialog;

    @Override
    protected void onPreExecute() {
        dialog = new ProgressDialog(baraj_mapa.this);
        dialog.setTitle("Calculating...");
        dialog.setMessage("Please wait...");
        dialog.setIndeterminate(true);
        dialog.show();
    }

    protected ArrayList<String> doInBackground(ArrayList<String>... passing) {

        //Some calculations...

        return something; //???
    }

    protected void onPostExecute(Void unused) {
        dialog.dismiss();
    }

Ma question est donc de savoir comment obtenir les éléments de la liste de tableaux "de passage" dans le AsyncTask doInBackground méthode (et les utiliser là-bas), et comment renvoyer une liste de tableaux à utiliser dans la méthode principale (la liste de tableaux "résultat")?

36
Bojan Ilievski

Changez votre méthode pour ressembler à ceci:

String curloc = current.toString();
String itemdesc = item.mDescription;
ArrayList<String> passing = new ArrayList<String>();
passing.add(itemdesc);
passing.add(curloc);
new calc_stanica().execute(passing); //no need to pass in result list

Et changez l'implémentation de votre tâche asynchrone

public class calc_stanica extends AsyncTask<ArrayList<String>, Void, ArrayList<String>> {
ProgressDialog dialog;

    @Override
    protected void onPreExecute() {
        dialog = new ProgressDialog(baraj_mapa.this);
        dialog.setTitle("Calculating...");
        dialog.setMessage("Please wait...");
        dialog.setIndeterminate(true);
        dialog.show();
    }

    protected ArrayList<String> doInBackground(ArrayList<String>... passing) {
        ArrayList<String> result = new ArrayList<String>();
        ArrayList<String> passed = passing[0]; //get passed arraylist

        //Some calculations...

        return result; //return result
    }

    protected void onPostExecute(ArrayList<String> result) {
        dialog.dismiss();
        String minim = result.get(0);
        int min = Integer.parseInt(minim);
        String glons = result.get(1);
        String glats = result.get(2);
        double glon = Double.parseDouble(glons);
        double glat = Double.parseDouble(glats);
        GeoPoint g = new GeoPoint(glon, glat);
        String korisni_linii = result.get(3);
    }

UPD:

Si vous souhaitez avoir accès au contexte de démarrage de la tâche, le moyen le plus simple serait de remplacer onPostExecute en place:

new calc_stanica() {
    protected void onPostExecute(ArrayList<String> result) {
      // here you have access to the context in which execute was called in first place. 
      // You'll have to mark all the local variables final though..
     }
}.execute(passing);
64
Konstantin Burov

Pourquoi voudriez-vous passer une liste de tableaux ?? Il devrait être possible d'appeler directement execute avec les paramètres:

String curloc = current.toString();
String itemdesc = item.mDescription;
new calc_stanica().execute(itemdesc, curloc)

Voilà comment les varrargs fonctionnent, non? Faire un ArrayList pour passer la variable est un double travail.

12
Leander

Je suis en quelque sorte d'accord avec Leander sur celui-ci.

appel:

new calc_stanica().execute(stringList.toArray(new String[stringList.size()]));

tâche:

public class calc_stanica extends AsyncTask<String, Void, ArrayList<String>> {
        @Override
        protected ArrayList<String> doInBackground(String... args) {
           ...
        }

        @Override
        protected void onPostExecute(ArrayList<String> result) {
           ... //do something with the result list here
        }
}

Ou vous pouvez simplement faire de la liste de résultats un paramètre de classe et remplacer ArrayList par un booléen (succès/échec);

public class calc_stanica extends AsyncTask<String, Void, Boolean> {
        private List<String> resultList;

        @Override
        protected boolean doInBackground(String... args) {
           ...
        }

        @Override
        protected void onPostExecute(boolean success) {
           ... //if successfull, do something with the result list here
        }
}
4
Stijn Bollen

Je ne le fais pas comme ça. Je trouve plus facile de surcharger le constructeur de la classe asychtask ..

la classe publique calc_stanica étend AsyncTask>

String String mWhateveryouwantToPass;

 public calc_stanica( String whateveryouwantToPass)
{

    this.String mWhateveryouwantToPass = String whateveryouwantToPass;
}
/*Now you can use  whateveryouwantToPass in the entire asynchTask ... you could pass in a context to your activity and try that too.*/   ...  ...  
1
j2emanue

Vous pouvez recevoir des résultats de retour comme celui-ci: AsyncTask class

@Override
protected Boolean doInBackground(Void... params) {
    if (Host.isEmpty() || dbName.isEmpty() || user.isEmpty() || pass.isEmpty() || port.isEmpty()) {
        try {
            throw new SQLException("Database credentials missing");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    try {
        Class.forName("org.postgresql.Driver");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

    try {
        this.conn = DriverManager.getConnection(this.Host + ':' + this.port + '/' + this.dbName, this.user, this.pass);
    } catch (SQLException e) {
        e.printStackTrace();
    }

    return true;
}

classe de réception:

_store.execute();
boolean result =_store.get();

En espérant que cela vous aidera.

0
Michael