2010-04-24 16 views
15

Tengo una actividad de Android que toma un RSS de una URL y usa el analizador SAX para pegar cada elemento del XML en una matriz. Todo esto funciona bien pero, como era de esperar, toma un poco de tiempo, por lo que quiero usar AsyncActivity para hacerlo en segundo plano. Mi código es el siguiente:Android ASync tarea ProgressDialog no se muestra hasta que termina el hilo de fondo

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

que llamo en onCreate() con

new AddTask().execute(); 

La línea items = parser.getItems() funciona bien - items ser el ArrayList que contiene cada elemento del XML. El problema al que me enfrento es que al iniciar la actividad, el ProgressDialog que creo en onPreExecute() no se muestra hasta que después de haya terminado el método doInBackground(). es decir, obtengo una pantalla negra, una pausa larga, y luego una lista completamente poblada con los elementos. ¿Por qué sucede esto? ¿Por qué no se muestra el dibujo de la interfaz de usuario, se muestra ProgressDialog, el analizador obtiene los elementos y los agrega incrementalmente a la lista, y luego se descarta ProgressDialog?

+0

En la parte "el analizador obtiene los elementos y los agrega incrementalmente a la lista", el paso lento estará en el análisis sintáctico y no agregará nada a la lista en ese punto. Por lo tanto, todos tus artículos se incluirán en la lista bastante rápido, así que no esperes mucho efecto "incremental" aquí. – CommonsWare

+0

Eso no es problema, realmente no me importa cuán "incrementales" son las inserciones, solo quiero que el archivo de progreso se muestre mientras se realiza el trabajo de fondo y desaparezca una vez que haya finalizado. – jackbot

Respuesta

10

Esto funciona para mí

@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

esto es realmente útil +1 –

+4

¿En qué se diferencia esto del código original de jackbot? Estás haciendo lo mismo con un ligero cambio. –

+3

esta no es la respuesta. No hay diferencia con el código original. –

13

sospecho que algo está bloqueando el hilo de interfaz de usuario después de ejecutar la tarea. Por ejemplo, he visto a gente hacer cosas como esta:

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

La invocación llegar hasta aquí va a bloquear el hilo de interfaz de usuario (que presumiblemente está girando fuera de la tarea aquí ...), lo que impide cualquier material relacionado con la interfaz de usuario en el método onPreExecute() de su tarea hasta que la tarea realmente se complete. ¡Ups! Espero que esto ayude.

+5

Votación por mencionar que una tarea.get bloquea la interfaz de usuario. Necesitaba ver eso en alguna parte. ¡Gracias! –

+0

Tiene el mismo problema. ¿Qué otra cosa puede bloquear la interfaz de usuario? hilo además del método get()? –

+0

usted señor es un héroe. ¡Gracias! – binaryguy

1

Si subclase la AsyncTask en su Actividad real, puede usar el método onPostExecute para asignar el resultado del trabajo de fondo a un miembro de su clase de llamada.

El resultado se pasa como un parámetro en este método, si se especifica como el tercer tipo genérico.

De esta forma, su Rosca UI no será bloqueada como se mencionó anteriormente. Sin embargo, debe tener en cuenta el uso posterior del resultado fuera de la subclase, ya que el hilo de fondo podría seguir ejecutándose y su miembro no tendría el nuevo valor.

4

Es porque usaste AsyncTask.get() que bloquea el hilo UI "Espera si es necesario para que se complete el cálculo, y luego recupera su resultado".

La forma correcta de hacerlo es pasar la instancia Activity a su AsyncTask por constructor y terminar lo que quiera en AsyncTask.onPostExecution().

+0

Eso es justo lo que estaba buscando, ¡muchas gracias! – Scadge

Cuestiones relacionadas