PDA

Ver la Versión Completa : Mi AsyncTask esta atascada en doInBackground()


Calibretto
01/04/14, 18:24:32
Hola, antes de nada saludar a todos los usuarios ya que este es mi primer mensaje, soy un programador bastante novato (acabo de salir del ciclo de DAM) y tengo un problema que me esta volviendo loco.

Tengo un programa que tiene que realizar una serie de acciones (leer de una hoja de calculo y sacar nombres), como tarda bastante quería poner un ProgressDialog para que el usuario se de cuenta de que esta trabajando.

Al principio ejecutaba el AsyncTask con execute().get() , obviamente el progressdialog no salia por que así bloqueo la UI hasta obtener el resultado, así que al final lo deje así:

private class GestionDatos extends AsyncTask<Void, Void, ArrayList<String>> {

@Override
protected void onPreExecute(){
super.onPreExecute();


mProgress = ProgressDialog.show(MainActivity.this, "Trabajando", "Espere por favor");
}


@Override
protected ArrayList<String> doInBackground(Void... params) {
SpreadsheetService service = new SpreadsheetService("com.banshee");
ArrayList<String> nombres = new ArrayList<String>();
String idAnterior = "idAnterior";
try {

String urlString = "My URL";

URL url = new URL(urlString);

ListFeed feed = service.getFeed(url, ListFeed.class);

for (ListEntry entry : feed.getEntries()) {
CustomElementCollection elements = entry
.getCustomElements();
String id = elements.getValue("Codigo");
if (idAnterior.compareTo(id) != 0) {
idAnterior = id;
String name = elements.getValue("Profesor");
nombres.add(name);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (ServiceException e) {
e.printStackTrace();
}

return nombres;
}

@Override
protected void onPostExecute(ArrayList<String> result){
super.onPostExecute(result);
mProgress.dismiss();
values = result;
}

}

El problema es que ahora el ProgressDialog si se muestra pero se queda ahí, bloqueado sin hacer nada, mediante unos Log.i me di cuenta de que en realidad si entra en el método doInBackground, pero no llega al for, así que de llegar al onPostExecute ni hablamos.

¿Alguien puede ayudarme? llevo ya un par de días con este tema, y seguro que al final es una bobada pero me estoy volviendo loco, gracias de antemano

PD: Ese values que veis ahi es un ArrayList<String> que tengo como atributo de la MainActivity

kriogeN
01/04/14, 20:00:42
Depura, ejecuta paso a paso y mira a ver en que línea se queda colgado, que tiene pinta de ser esta:

ListFeed feed = service.getFeed(url, ListFeed.class);

Calibretto
01/04/14, 20:27:22
Depura, ejecuta paso a paso y mira a ver en que línea se queda colgado, que tiene pinta de ser esta:

ListFeed feed = service.getFeed(url, ListFeed.class);

¿Seguro? cuando llamaba al AsyncTask con execute().get() el programa funcionaba perfectamente, la única diferencia es que ahora tengo preExecute() (por el progress dialog) y postExecute() para poder obtener el ArrayList<String> que antes obtenía con el get(), me resulta extraño

kriogeN
01/04/14, 23:47:31
Pues entonces no lo entiendo, porque el get() lo único que hace es esperar al resultado, pero el execute() se ejecuta exactamente igual. ¿Seguro que te devolvía la respuesta correcta y no se producía una excepción?

Calibretto
02/04/14, 15:33:19
He hecho mas pruebas, para enredar aun mas las cosas no me devuelve ninguna excepción y si quito el ProgressDialog funciona perfectamente, es decir, que en el momento que he puesto a funcionar el ProgressDialog deja de funcionar y solo puedo ver el mensaje de "Trabajando espere por favor" con la rueda girando hasta el final de los tiempos.....he ejecutado la tarea asincrona con execute y con .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null) por si acaso, pero nada de nada

Calibretto
02/04/14, 19:54:17
Nuevos datos, si doy al boton de ir atras del emulador el ProgressDialog se cierra y entonces la aplicacion se ejecuta correctamente, es decir, de alguna manera la ejecucion del ProgressDialog bloquea e impide que el doInBackGround se ejecute del todo

Me voy a pegar un tiro:loco:

checus
02/04/14, 21:02:43
Nuevos datos, si doy al boton de ir atras del emulador el ProgressDialog se cierra y entonces la aplicacion se ejecuta correctamente, es decir, de alguna manera la ejecucion del ProgressDialog bloquea e impide que el doInBackGround se ejecute del todo

Me voy a pegar un tiro:loco:

Tira un try catch a cada paso que das y sacalo por un toast. Si dices que el fallo mas o menos lo tienes localizado, el área se reduce, con eso deberías sacar la información del error.
Si no utilizas Hax, prueba a usar la aplicación en tu propio dispositivo que muchas veces el emulador no es una maravilla.

P.D. has revisado los permisos en el Manifest?

kriogeN
02/04/14, 21:33:16
El ProgressDialog se cierra porque es cancelable, cosa que por cierto no deberías permitir, ".setCancelable(false)". Pero no tiene ningún sentido que el ProgressDialog te bloquee la ejecución del código.

EDITO: Esto es un AsyncTask que tengo en mi app, y hago lo mismo que tú.

public class AsyncBorrarUsuario extends AsyncTask<Void, Void, Boolean>{

private Context context;

private TransparentProgressDialog dialog;

public AsyncBorrarUsuario(Context context){
this.context=context;
dialog = new TransparentProgressDialog(context,true);
}

@Override
protected void onPreExecute() {
this.dialog.show();
}

@Override
protected Boolean doInBackground(Void... params) {
return WebService.borrarUsuario(context);
}
@Override
protected void onPostExecute(Boolean result) {
dialog.dismiss();
}
}

TransparentProgressDialog es una subclase de Dialog que he creado para mostrar un ProgressDialog sobre un fondo transparente, y que además se establece a setCancelable(false)

Calibretto
03/04/14, 16:30:38
El ProgressDialog se cierra porque es cancelable, cosa que por cierto no deberías permitir, ".setCancelable(false)". Pero no tiene ningún sentido que el ProgressDialog te bloquee la ejecución del código.

EDITO: Esto es un AsyncTask que tengo en mi app, y hago lo mismo que tú.

public class AsyncBorrarUsuario extends AsyncTask<Void, Void, Boolean>{

private Context context;

private TransparentProgressDialog dialog;

public AsyncBorrarUsuario(Context context){
this.context=context;
dialog = new TransparentProgressDialog(context,true);
}

@Override
protected void onPreExecute() {
this.dialog.show();
}

@Override
protected Boolean doInBackground(Void... params) {
return WebService.borrarUsuario(context);
}
@Override
protected void onPostExecute(Boolean result) {
dialog.dismiss();
}
}

TransparentProgressDialog es una subclase de Dialog que he creado para mostrar un ProgressDialog sobre un fondo transparente, y que además se establece a setCancelable(false)

Podemos seguir acotando el problema, me he dado cuenta de que donde se queda bloqueado es en:
ListFeed feed = service.getFeed(url, ListFeed.class);

Tal y como dijistes, con unos Log.i me he dado cuenta de que el ultimo que puedo ver en el Logcat es el que tengo en la linea anterior al ListFeed, despues lo que puedo observar en el Logcat es infinidad de mensajes de "Skipped 30 frames! The application may be doing too much work on its main thread." pero con diferente numero de frames cada vez.

Por lo visto debe ser demasiado trabajo, lo que no entiendo es por que sin el ProgressDialog la aplicacion funciona bien y con el puesto no

Calibretto
09/04/14, 14:36:21
Al final solucione el problema, y es que al parecer el problema no era del código, era del hardware, os cuento.

Resulta que en eclipse uso el emulador con kitkat (API 19, 4.4.2), pensé que ese podía ser el problema así que cree otra máquina virtual con JellyBean (API 18, 4.3) y ejecuté el programa, el resultado fue exactamente el mismo.

Pues hoy me da por hacer lo mismo en mi portátil, el eclipse que tengo en el trabaja con 4.3,y...!oh sorpresa! funcionaba perfectamente, llegados a este punto aclarar que el código era el mismo solo cambió el pc.

Entonces viene la pregunta del millón: ¿por que? ¿quizás al ser una tarea muy pesada la que tenia que realizar (sacar datos de una hoja de cálculo de Google con 2000 y pico registros) el equipo no diera mas de si y no pudiera dedicar el suficiente tiempo de CPU para realizarla? no probé a dejarlo trabajar mas tiempo, como máximo un cuarto de hora o 20 minutos, me parecía un tiempo inaceptable y salía de la aplicación siempre ¿si lo hubiera dejado mas tiempo habría acabado?

La máquina en la que probe en primer lugar es un AMD Athlon 64 X2 Dual core 2,40GHz con 2GB de memoria RAM, mientras que mi portatil es un i7 con 6GB de memoria RAM, ambas maquinas virtuales eran iguales en caracteristicas ¿Que opinais?

Muchas gracias a todos los que hayais dedicado algo de tiempo en ayudarme

kriogeN
09/04/14, 16:49:45
Dalo por hecho, mi portátil es un Dual Core 1.7Ghz 64 bits con 4 GB de RAM y el emulador de 4.1 en adelante ni me abre.

Si no puedes probarlo en un dispositivo físico te recomiendo que uses BlueStacks, es 4.0 (o 4.1, ahora mismo no lo recuerdo bien) y funciona casi a la misma velocidad que un dispositivo físico. En mi portátil las aplicaciones me funcionan a la misma velocidad que el dispositivo físico.

La única pega es que no podrás probar aplicaciones que requieran de librerías nativas basadas en ARM.

EDITO: También puedes probar Genymotion, que lleva también para KitKat, yo aún no lo he probado pero justo voy a hacerlo.