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")?
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);
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.
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
}
}
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.*/ ... ...
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.