2012-04-03 16 views
37

Ho una funzione, AppHelper.isOnline(Context context), chiamo in varie parti della mia applicazione per verificare che una sessione non abbia scaduto prima di fare una richiesta HTTP.Android attendere AsyncTask per finire

public void onClick(View v) { 
     Intent intent = null; 
     switch (v.getId()) { 

     case R.id.buttonPagamenti: 
      if (AppHelper.isOnline(this)) 
      { 
       //here AppHelper.isOnline should have finished it's async task 
       intent = new Intent(this, OrdineCreaActivity.class); 
       this.startActivityForResult(intent, R.id.buttonPagamenti); 
      } 
      break; 
... 

All'interno AppHelper.isOnline(), sto eseguendo una AsyncTask che accede, rendendo così una richiesta di rete, che non può essere eseguito su UI perché altrimenti ottengo un'eccezione. Devo aspettare che finisca PRIMA di riprendere con il codice all'interno del if. Come posso fare questo ?

Il problema è che l'attività inizia primariamente, quindi viene eseguito AsyncTask, quindi quando l'attività si aspetta una sessione di accesso valida, si interrompe.

risposta

81

si hanno due opzioni:

O utilizzare il metodo get(long timeout, TimeUnit unit) s' il AsyncTask del genere:

task.get(1000, TimeUnit.MILLISECONDS); 

Questo renderà il vostro thread principale attesa per il risultato della AsyncTask al massimo 1000 millisecondi (come per commento @ user1028741: in realtà c'è anche il metodo infinitamente attesa - AsyncTask#get() che potrebbe anche funzionare in alcuni casi per voi).

In alternativa è possibile visualizzare una finestra di dialogo di avanzamento nell'attività asincrona fino al termine. Vedi questo thread (Non c'è bisogno che copi il codice). Fondamentalmente viene visualizzata una finestra di avanzamento mentre l'attività asincrona viene eseguita e viene nascosta al termine.

avete anche terza opzione:" se Thread è sufficiente per le vostre esigenze si può semplicemente utilizzare il suo metodo join Tuttavia, se l'attività è in corso da molto tempo sarà ancora bisogno di mostrare una finestra di avanzamento, altrimenti si otterrà. un'eccezione a causa del thread principale essere stato inattivo per troppo tempo.

+0

ho provato il join, ma il problema è async.exec() non si avvia prima che il join entri in gioco, quindi l'app rimane indefinita, quindi proverò a provare l'attività.get – max4ever

+2

l'attività asincrona ha una finestra di dialogo di avanzamento ma non impedisce alla nuova attività di iniziare – max4ever

+1

task.get() è proprio quello di cui avevo bisogno, grazie !!! – max4ever

1
intent = new Intent(this, OrdineCreaActivity.class); 
context.startActivityForResult(intent, R.id.buttonPagamenti); 

Scrivi le righe di cui sopra in OnPostExecute() di voi AysncTask. perché se stiamo usando AsyncTask è solito aspettare lì fino a quando il compito completo.

+0

sì, ma a volte non ho bisogno di iniziare una nuova attività forse faccio altre cose, ho bisogno di interrompere il thread dell'interfaccia utente principale e attendere l'asincrono – max4ever

+0

non ho capito puoi essere più specifico –

+0

in alcuni punti della mia applicazione ho bisogno di verificare se l'utente è loggato e se non ho bisogno di login automatico per lui, vorrei fare in modo di creare 3000 diversi callback (per onPostExecute da chiamare) – max4ever

3

prova usando

if (AppHelper.isOnline(this)) 
     { 
      while(!task.isCancelled()){ 
       // waiting until finished protected String[] doInBackground(Void... params)   
       } 
      intent = new Intent(this, OrdineCreaActivity.class); 
      this.startActivityForResult(intent, R.id.buttonPagamenti); 
     }  

Per ulteriori informazioni leggere http://developer.android.com/reference/android/os/AsyncTask.html

+0

e da dove ottengo la variabile di attività? Devo cambiare isOnline da booleano a AsyncTask? – max4ever

+0

AsyncTask task = new AppHelper(); task.execute(); – Rafiq

+0

AppHelper deve estendere AsyncTask e implementare il metodo doInBackground (...), onPostExecute (...), ecc. – Rafiq

2

risposta di Rafiq non ha funzionato per me - l'applicazione appeso. Penso che la ragione abbia a che fare con la natura di isCancelled(): "Restituisce true se quest'attività è stata cancellata prima che fosse completata normalmente." Se l'attività viene completata normalmente (ovvero non viene annullata), allora while(!task.isCancelled()) { } si interrompe per sempre.

Per risolvere questo problema, creare un flag booleano da instaziare a false e quindi passare a true in task.onPostExecute(). Quindi fare while(!flag) { } prima di cambiare Attività. Inoltre, se si desidera dare il thread principale di un 'break' per lasciare che il processo di AsyncTask un po 'più veloce, si può fare provare questo:

while (!flag) { 
    try { Thread.sleep(100); } 
    catch (InterruptedException e) { e.printStackTrace(); } 
} 

Sembra funzionare bene per me.

+0

Questo è esattamente quello che sto cercando di fare, ma per qualche motivo il metodo onPostExecute non viene chiamato così l'interfaccia utente rimane bloccata nel metodo Thread.sleep. – emiliosg

+1

@Emiliosg - Sei sicuro che il tuo AsyncTask stia completando? Se AsyncTask non viene mai completato, non otterrai mai "onPostExecute()" e resterai in attesa. Prova ad aggiungere alcuni logging al tuo 'doInBackground()' per assicurarti che stia facendo correttamente quello che dovrebbe fare. –

+0

Non è una buona idea usare un'attesa molto attiva, fare riferimento a https://www.facebook.com/arig/posts/10105815276466163 –

Problemi correlati