2010-04-24 11 views
15

Ho un'attività Android che acquisisce un feed RSS da un URL e utilizza il parser SAX per attaccare ogni elemento dall'XML in un array. Funziona tutto bene ma, come previsto, richiede un po 'di tempo, quindi voglio usare AsyncActivity per farlo in background. Il mio codice è il seguente:Attività ASync Android ProgressDialog non viene visualizzato fino al termine del thread di sfondo

class AddTask extends AsyncTask<Void, Item, Void> { 

    protected void onPreExecute() { 
     pDialog = ProgressDialog.show(MyActivity.this,"Please wait...", "Retrieving data ...", true); 
    } 

    protected Void doInBackground(Void... unused) { 
     items = parser.getItems(); 

     for (Item it : items) { 
      publishProgress(it); 
     } 
     return(null); 
    } 

    protected void onProgressUpdate(Item... item) { 
     adapter.add(item[0]); 
    } 

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

che io chiamo in onCreate() con

new AddTask().execute(); 

La linea items = parser.getItems() funziona bene - items essere l'arraylist contenente ogni elemento dal XML. Il problema che sto affrontando è che all'avvio dell'attività, la ProgressDialog che creo in onPreExecute() non viene visualizzata fino al dopo il il metodo doInBackground() è terminato. io ottengo uno schermo nero, una lunga pausa, poi una lista completamente popolata con gli elementi in. Perché sta succedendo? Perché il disegno dell'interfaccia utente non viene visualizzato, la ProgressDialog mostra, il parser ottiene gli elementi e li aggiunge in modo incrementale alla lista, quindi il ProgressDialog si chiude?

+0

Nella parte "il parser che ottiene gli elementi e aggiungendoli in modo incrementale all'elenco", il passo lento sarà nell'analisi e non si aggiungerà nulla all'elenco in quel punto. Quindi, tutti i tuoi articoli verranno inseriti nella lista abbastanza velocemente, quindi non aspettarti qui un effetto "incrementale". – CommonsWare

+0

Questo non è un problema, non mi interessa quanto siano "incrementali" gli inserimenti, voglio solo che ProgressDialog si mostri mentre il lavoro in background è fatto e scompare una volta finito. – jackbot

risposta

10

questo funziona per me

@Override 
protected void onPreExecute() { 
     dialog = new ProgressDialog(viewContacts.this); 
     dialog.setMessage(getString(R.string.please_wait_while_loading)); 
     dialog.setIndeterminate(true); 
     dialog.setCancelable(false); 
     dialog.show(); 
    } 
+0

questa cosa è veramente utile +1 –

+4

Come è diverso dal codice originale di jackbot? Stai solo facendo la stessa cosa con un leggero cambiamento. –

+3

questa non è la risposta. Non c'è differenza con il codice originale. –

13

Ho il sospetto che qualcosa sta bloccando il tuo thread dell'interfaccia utente dopo aver eseguito l'operazione. Ad esempio, ho visto gente fare le cose in questo modo:

MyTask myTask = new MyTask(); 
TaskParams params = new TaskParams(); 
myTask.execute(params); 
myTask.get(5000, TimeUnit.MILLISECONDS); 

La get invocazione qui sta andando a bloccare il thread UI (che presumibilmente sta filando via il compito qui ...) che impedirà qualsiasi materiale correlato UI nel tuo metodo onPreExecute() della tua attività fino al completamento effettivo dell'attività. Ops! Spero che questo ti aiuti.

+5

Upvote per aver menzionato che task.get blocca l'interfaccia utente. Devo vederlo da qualche parte. Grazie! –

+0

Avere lo stesso problema. Cos'altro può bloccare l'interfaccia utente thread oltre al metodo get()? –

+0

sei un eroe, grazie! – binaryguy

1

Se si sottoclasse AsyncTask nell'attività corrente, è possibile utilizzare il metodo onPostExecute per assegnare il risultato del lavoro in background a un membro della classe chiamante.

Il risultato viene passato come parametro in questo metodo, se specificato come terzo tipo generico.

In questo modo, il thread dell'interfaccia utente non verrà bloccato come menzionato sopra. Devi comunque occuparti di qualsiasi utilizzo successivo del risultato al di fuori della sottoclasse, poiché il thread in background potrebbe ancora essere in esecuzione e il tuo membro non avrebbe il nuovo valore.

4

È perché è stato utilizzato AsyncTask.get() che blocca il thread dell'interfaccia utente "Attende, se necessario, il completamento del calcolo e quindi recupera il risultato.".

Il modo corretto per farlo è passare l'istanza Activity al tuo AsyncTask dal costruttore e terminare tutto ciò che vuoi fare in AsyncTask.onPostExecution().

+0

Questo è proprio quello che stavo cercando, grazie mille! – Scadge

Problemi correlati