Programación y Desarrollo para Android Subforo exclusivo para temas de programación de software para PDAs y desarrollo de aplicaciones, interfaces, etc bajo Android

Respuesta
 
Herramientas
  #1  
Viejo 15/09/15, 10:44:49
Array

[xs_avatar]
javichechu javichechu no está en línea
Usuario poco activo
 
Fecha de registro: sep 2015
Mensajes: 6
Modelo de smartphone: Galaxy S3 y Iphone6
Tu operador: Movistar
interrogacion Crear Hilo de Carga de Datos

Buenos días.
Quería expresaros mi problema a ver si me pueden dar una solución o alguna pista.


En mi aplicación nativa Android, realizada con AndroidStudio, estoy haciendo un procedimiento de carga masiva al inicio de la aplicación, de manera que recibe vía SErvicio Web ciertos datos relevantes, y estos los guarda en la Base de Datos interna de la aplicación para evitar tener que llamar al SW nuevamente.

Esta tarea, la tengo pensada para que se ejecute al inicio, sale el clásico "Loading..." para que el usuario sepa que se está trabajando, y la intención es que tras finalizar, se vaya al Main de la App.

El problema es el siguiente. Como el thread pricipal, a su vez llama a métodos que por narices, tiene que ir en thread (Llamada a Servicio Web y Descarga de Imágenes) me está pasando que el thread principal termina antes de que los invocados dentro de él terminen, y por lo tanto, se va al Main antes de haber terminado de inertar datos en la BBDD y descargado las imágenes que también insertará en la BBDD.

Necesito lograr, que el proceso principal que regula toda esta carga inicial, quede en "Loading" hasta que los demás thread terminen.

¿cómo puedo lograr esto??? Mil gracias.
Responder Con Cita


  #2  
Viejo 15/09/15, 12:36:19
Array

[xs_avatar]
kriogeN kriogeN no está en línea
Colaborador/a
· Votos compra/venta: (1)
 
Fecha de registro: oct 2010
Localización: Murcia
Mensajes: 4,637
Modelo de smartphone: Samsung Galaxy S7 Edge SM-G935F
Tu operador: Vodafone
Forma básica de Android:

Con un AsyncTask, el código que lanza a la segunda Activity una vez ha terminado de llamar al servicio web y descargar imágenes lo pones en el onPostExecute. Y el código que hace toda la descarga en el doInBackground.

Forma mejor:

Con la librería Volley de Google, en el Response.Listener pones el código que abre a la segunda Activity.
Responder Con Cita
  #3  
Viejo 15/09/15, 13:49:30
Array

[xs_avatar]
javichechu javichechu no está en línea
Usuario poco activo
 
Fecha de registro: sep 2015
Mensajes: 6
Modelo de smartphone: Galaxy S3 y Iphone6
Tu operador: Movistar
Hola.
Gracias por la contestación

Es precisamente un AsyncTask lo que utilizo para regular el proceso de carga masiva de datos. Dicho proceso, tiene en el doInBackground la creación de objeto de una clase que hace todas las operaciónes, y luego en el onPostExecute, hacemos la finalización del "Loading" y navegación hacia el Main de la app.

Etonces, y entrando en el Turrón, es el doInBackground de este AsyncTask principal, quien llama a un método que se encarga de hacer todo. Ese método hace dos cosas. Por un lado llama a los Servicios Web con otro AsyncTask, y en su onPostExecute rellenamos un array de objetos con esa información, y posteriormetne llama a otro AsyncTask, que cogiendo de esos objetos las rutas de unas imágenes lad descarga para finalmente tras la descarga, en su onPostExecute ya hace la insercción de datos e imágenes a la base de datos de la APP.

¿cómo me está funcionando? Pues el proceso principal, tras llamar al método que inicia la carga de todo desde su doInBackground, pasa por su onPostExecute y por ello se va al Main antes de que el resto de AsyncTask "hijas" terminen de trabajar, y por lo tanto, mientras la app sigue operando, por detrás está haciendo la carga de datos, descarga de imágenes y posterior insercción en BBDD, cuando lo que deseo, es que el loading se mantenga hasta que todo esto termine.

Siento que esto quede algo confuso, no se si me he explicado bien.

Gracias.
Responder Con Cita
  #4  
Viejo 15/09/15, 13:56:34
Array

[xs_avatar]
kriogeN kriogeN no está en línea
Colaborador/a
· Votos compra/venta: (1)
 
Fecha de registro: oct 2010
Localización: Murcia
Mensajes: 4,637
Modelo de smartphone: Samsung Galaxy S7 Edge SM-G935F
Tu operador: Vodafone
Puedes anidar los AsyncTask, de tal forma que uno no empieza hasta que termine el otro.

O puedes poner 3 banderas (una en cada AsyncTask). Cada AsyncTask activa su bandera y comprueba si las otras 2 banderas están activadas. Si lo están pasa a la siguiente Activity, si no no hacen nada, ya lo hará el último AsyncTask que termine.
Responder Con Cita
  #5  
Viejo 15/09/15, 14:53:11
Array

[xs_avatar]
javichechu javichechu no está en línea
Usuario poco activo
 
Fecha de registro: sep 2015
Mensajes: 6
Modelo de smartphone: Galaxy S3 y Iphone6
Tu operador: Movistar
 Cita: Originalmente Escrito por kriogeN Ver Mensaje
Puedes anidar los AsyncTask, de tal forma que uno no empieza hasta que termine el otro.

O puedes poner 3 banderas (una en cada AsyncTask). Cada AsyncTask activa su bandera y comprueba si las otras 2 banderas están activadas. Si lo están pasa a la siguiente Activity, si no no hacen nada, ya lo hará el último AsyncTask que termine.
Eso de las banderas me interesa...
¿Me puedes dar algo más de detalle o por Bandera te refieres a un booleano y listo?? Porque veo que los AsyncTask tienen una comprobación de su estado, si está running y demás, pero no consigo hacerlo con eso y algún sleep

Responder Con Cita
  #6  
Viejo 15/09/15, 16:35:33
Array

[xs_avatar]
kriogeN kriogeN no está en línea
Colaborador/a
· Votos compra/venta: (1)
 
Fecha de registro: oct 2010
Localización: Murcia
Mensajes: 4,637
Modelo de smartphone: Samsung Galaxy S7 Edge SM-G935F
Tu operador: Vodafone
 Cita: Originalmente Escrito por javichechu Ver Mensaje
Eso de las banderas me interesa...
¿Me puedes dar algo más de detalle o por Bandera te refieres a un booleano y listo?? Porque veo que los AsyncTask tienen una comprobación de su estado, si está running y demás, pero no consigo hacerlo con eso y algún sleep

Por bandera me refiero a un booleano, si.

Imagina que tus procesos son solo 2, descargar los datos y descargar imágenes, y cada una lo haces en 2 AsyncTask distintos. Hasta que no terminen ambos no muestras la siguiente Activity.

Tienes un método llamado lanzarActivity() (por simplificar) y 2 Booleanos globales en tu Activity, uno llamado "terminaDatos" y el otro "terminaImagenes", ambos inicializados a false.

En el onPostExecute de la descarga de los datos haces:

terminaDatos = true;
if (terminaImagenes)
{
lanzarActivity();
}

Y en el onPostExecute() de la descarga de imágenes tienes el contrario:

terminaImagenes = true;
if (terminaDatos)
{
lanzarActivity();
}

Como los onPostExecute siempre se ejecutan en primer plano no hay problemas de concurrencia, hasta que no termine uno no empezará el otro. Con lo cual tu Activity sólo se lanzará 1 vez, aquella que termine la última.

NOTA: No pongo "terminaImagenes && terminaDatos" en los "if" (que es lo que de verdad debería lanzar la Activity) porque ya se establecen a true en su propio onPostExecute, con lo cual es un absurdo porque siempre son "true", pero si quieres ponerlo por claridad de código no está mal.
Responder Con Cita
  #7  
Viejo 15/09/15, 17:42:50
Array

[xs_avatar]
mocelet mocelet no está en línea
Desarrollador
 
Fecha de registro: may 2011
Localización: Madrid
Mensajes: 2,203
Tu operador: -

Las async task desde que cambiaron el executor por defecto en Android ¿4.0? a un sólo hilo no tienen mucha gracia para tareas en paralelo porque se encolan salvo que se indique lo contrario.

Así que lo más probable es que hasta que no termine una asynctask no ejecute la siguiente. Lo comento de cara a futuras optimizaciones, aunque lo suyo es usar alguna biblioteca tipo Volley como indicaba kriogeN.
__________________
El mejor Cuatro en Raya de Android (Hilo en HTCMania, Play Store) ¡Un millón de descargas!
Responder Con Cita
  #8  
Viejo 15/09/15, 18:09:56
Array

[xs_avatar]
kriogeN kriogeN no está en línea
Colaborador/a
· Votos compra/venta: (1)
 
Fecha de registro: oct 2010
Localización: Murcia
Mensajes: 4,637
Modelo de smartphone: Samsung Galaxy S7 Edge SM-G935F
Tu operador: Vodafone
 Cita: Originalmente Escrito por mocelet Ver Mensaje
Las async task desde que cambiaron el executor por defecto en Android ¿4.0? a un sólo hilo no tienen mucha gracia para tareas en paralelo porque se encolan salvo que se indique lo contrario.

Así que lo más probable es que hasta que no termine una asynctask no ejecute la siguiente. Lo comento de cara a futuras optimizaciones, aunque lo suyo es usar alguna biblioteca tipo Volley como indicaba kriogeN.
Si, ya he dicho que era mejor forma, yo desde que descubrí Volley no uso otra cosa. Lo uso hasta para cachear imágenes y así también prescindo de Picasso y derivados.

Pero claro, adaptar una app entera para que use Volley es un trabajo, por eso he dicho que la más fácil era poner banderas en las AsyncTask.
Responder Con Cita
  #9  
Viejo 16/09/15, 16:23:43
Array

[xs_avatar]
javichechu javichechu no está en línea
Usuario poco activo
 
Fecha de registro: sep 2015
Mensajes: 6
Modelo de smartphone: Galaxy S3 y Iphone6
Tu operador: Movistar
Voy a mirar Volley también. Me parece interesante porque he visto aspectos importantes como evitar o corregir el parpadeo en la carga masiva de imágenes, ya que es algo que voy a utilizar mucho en la carga de Listados que tienen imágenes y he visto que Volley es potente también para eso.
Responder Con Cita
  #10  
Viejo 16/09/15, 23:16:42
Array

[xs_avatar]
Dexafree Dexafree no está en línea
Mr. FAQMan
· Votos compra/venta: (1)
 
Fecha de registro: dic 2008
Mensajes: 8,021
Modelo de smartphone: Samsung Galaxy S i9000 + Galaxy Tab 10.1 WiFi
Tu operador: Movistar
Aqui un fan acérrimo de Picasso (probé Glide pero no me terminó de gustar).
Para peticiones a API soy bastante fan de Ion, aunque tengo pendiente probar Retrofit.

Por si sirve, un compi del foro ( @Arasthel ) creó AsyncJob para no tener que lidiar más con las AsyncTask para tareas sencillas: https://github.com/Arasthel/AsyncJobLibrary

El uso es super sencillo, sobretodo con los métodos estáticos.

Queda algo tal que

Código:
AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() {
    @override
    public void doOnBackground() {

        // Pretend it's doing some background processing
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // Create a fake result (MUST be final)
        final boolean result = true;

        // Send the result to the UI thread and show it on a Toast
        AsyncJob.doOnMainThread(new AsyncJob.OnMainThreadJob() {
            @override
            public void doInUIThread() {
                Toast.makeText(context, "Result was: "+ result, Toast.LENGTH_SHORT).show();
            }
        });
    }
});
Y ya si usas retrolambda quedan métodos preciosos en los que puedes controlar de forma sencilla qué se hace en segundo plano y qué se hace en primer plano
Responder Con Cita
  #11  
Viejo 17/09/15, 09:11:30
Array

[xs_avatar]
javichechu javichechu no está en línea
Usuario poco activo
 
Fecha de registro: sep 2015
Mensajes: 6
Modelo de smartphone: Galaxy S3 y Iphone6
Tu operador: Movistar
Finalmente lo hice con banderas y funciona bastante bien.
El resumen es el siguiente.

1- Desde la Activity tengo un AsyncTask que controla la carga principal. Ese AsyncTask levanta la animación del "Cargando...".

2- Desde esa AsyncTask se crea un objeto para hacer todas las operaciones. En el constructor le paso la propia Activity. Invoco entonces al método de dicho objeto que hará la carga principal.

3- Dentro de ese método se hacen tres cosas. Cargar Cagegorías, cargar Subcategorías y cargar Características. Cada una de esas acciones, hace 3 AsyncTask. Una para invocar al WebServices y capturar los datos en Json. Otra para descargar imágenes de cierto campo que nos llega en ese json, y por último, otro para una vez tenemos los objetos montados, rellenando sus campos con los datos sacados del json y la imagen descargada, insertar la información en la Base de Datos de la APP.

4- Cada uno de esos procesos, en su onPostExecute llama a un método denominado ValidarFin, que lo que hace es comprobar si la bandera de cada uno de los tres procesos iniciados está levantada. En caso de estar levantadas todas, utilizando la Activity que recibe en el constructor, invoca al método "DotoMain" que ya hace un intent para ir al Main de la App y finalizar la carga.

5- A partir de esa carga inicial, que meto los datos en la BBDD, ya no tengo que hacer más llamadas al Servicio Web, dado que saco la información desde la BBDD de la APP, lo cual funciona bastante bien y ahorra llamadas a un Servicio Web. Cuantas más llamadas ahorre, mejor. No queremos extresarle... XD


Con esto, funciona perfectamente y la app queda en en la pantalla de Loading hasta que todos sus "subProcesos" terminen.

¿Aparte de usar volley, que iventisgaré con detenimiento... existe alguna recomendación más?


PD: Ya había visto Piccasso trasteqando por ahí. Me parece muy interesante. Como en ciertas partes, tengo galerías de imágenes a mostrar... le voy a pegar un buen vistazo a esta librería porque según he leído, merece muy mucho la pena.
Responder Con Cita
Respuesta

Estás aquí
Regresar   Portal | Indice > Todo sobre Android > Programación y Desarrollo para Android



Hora actual: 04:57:45 (GMT +1)



User Alert System provided by Advanced User Tagging (Lite) - vBulletin Mods & Addons Copyright © 2026 DragonByte Technologies Ltd.

Contactar por correo / Contact by mail / 邮件联系 /