2010-11-16 9 views
34

Ho un'applicazione che esegue alcuni lunghi calcoli e vorrei mostrare una finestra di avanzamento mentre questo è fatto. Finora ho scoperto che avrei potuto farlo con thread/handler, ma non ha funzionato, e poi ho scoperto lo AsyncTask.Passare argomenti a AsyncTask e restituire i risultati

Nella mia applicazione utilizzo mappe con marcatori e ho implementato la funzione onTap per chiamare un metodo che ho definito. Il metodo crea una finestra di dialogo con i pulsanti Sì/No e vorrei chiamare un AsyncTask se si fa clic su Sì. La mia domanda è come passare uno allo AsyncTask (e lavorarci lì), e come ottenere un nuovo ArrayList<String> come risultato dal AsyncTask?

Il codice del metodo assomiglia a questo:

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

Quindi, come vedete, vorrei inviare la stringa lista di array "passaggio" al AsyncTask, e per ottenere il "risultato" stringa elenco di matrice da esso. E la classe calc_stanica AssycTask si presenta così:

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

Quindi la mia domanda è come ottenere gli elementi della lista di array "passaggio" nel metodo AsyncTask doInBackground (e li usa lì), e come restituire una lista di array da usare nel metodo principale (la lista di matrice "risultato")?

risposta

61

cambiare il metodo di simile a questa:

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 

e cambiare l'implementazione compito asincrona

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:

Se si vuole avere accesso al compito partenza contesto, il modo più semplice sarebbe quello di ignorare onPostExecute sul posto:

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); 
+0

Grazie per la risposta, ma ho ancora una cosa da chiedere. Se definisco int min = Integer.parseInt (minim); ad esempio, nella classe AsyncTask suPostExecute(), come posso accedervi dal mio metodo di classe principale? Quando lo cambio in questo modo, ottengo l'errore "min non può essere risolto" nel metodo della classe principale. –

+2

@Bojan Ilievski: basta rendere globale la variabile min. – Wroclai

+0

Grazie per aver risposto di nuovo, ho risolto i miei problemi ... –

12

Perché passare una lista array ?? Dovrebbe essere possibile chiamare solo eseguire con i params direttamente:

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

Ecco come varrargs lavoro, giusto? Fare una lista array per passare la variabile è un lavoro doppio.

+0

Sono assolutamente d'accordo con Leander qui. In ogni caso, per cambiare il segno di spunta corretto della risposta? –

4

Sono un po 'più d'accordo con questo.

chiamata:

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

compito:

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 
     } 
} 

Oppure si può semplicemente fare la lista dei risultati di un parametro di classe e sostituire l'ArrayList con un valore booleano (successo/insuccesso);

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 
     } 
} 
1

I dont fare in questo modo. Trovo più facile sovraccaricare il costruttore della classe asychtask.

public class calc_stanica estende 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.*/ ... ... 
0

È possibile ricevere restituire i risultati del genere: AsyncTask classe

@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 di ricezione:

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

Sperando t aiuterà.

Problemi correlati