Todos los componentes de una aplicación Android, tanto las actividades, los servicios [sí, también los servicios], o los broadcast receivers se ejecutan en el mismo hilo de ejecución, el llamado hilo principal, main thread o GUI thread, que como éste último nombre indica también es el hilo donde se ejecutan todas las operaciones que gestionan la interfaz de usuario de la aplicación. Es por ello, que cualquier operación larga o costosa que realicemos en este hilo va a bloquear la ejecución del resto de componentes de la aplicación y por supuesto también la interfaz, produciendo al usuario un efecto evidente de lentitud, bloqueo, o mal funcionamiento en general, algo que deberíamos evitar a toda costa. Incluso puede ser peor, dado que Android monitoriza las operaciones realizadas en el hilo principal y detecta aquellas que superen los 5 segundos, en cuyo caso se muestra el famoso mensaje de «Application Not Responding» (ANR) y el usuario debe decidir entre forzar el cierre de la aplicación o esperar a que termine.
Obviamente, éstos son el tipo de errores que nadie quiere ver al utilizar su aplicación, y en este artículo y los siguientes vamos a ver varias formas de evitarlo utilizando procesos en segundo plano para ejecutar las operaciones de larga duración. En este primer artículo de la serie nos vamos a centrar en dos de las alternativas más directas a la hora de ejecutar tareas en segundo plano en Android:
- Crear nosotros mismos de forma explícita un nuevo hilo para ejecutar nuestra tarea.
- Utilizar la clase auxiliar AsyncTask proporcionada por Android.
Mi idea inicial para este artículo era obviar la primera opción, ya que normalmente la segunda solución nos es más que suficiente, y además es mas sencilla y más limpia de implementar. Sin embargo, si no comentamos al menos de pasada la forma de crear «a mano» nuevos hilos y los problemas que surgen, quizá no se viera demasiado claro las ventajas que tiene utilizar las AsyncTask. Por tanto, finalmente voy a pasar muy rápidamente por la primera opción para después centrarnos un poco más en la segunda. Además, aprovechando el tema de la ejecución de tareas en segundo plano, vamos a ver también cómo utilizar un control (el ProgressBar) y un tipo de diálogo (el ProgressDialog) que no vimos en los primeros temas del curso dedicados a la interfaz de usuario.
Y para ir paso a paso, vamso a empezar por crear una aplicación de ejemplo en cuya actividad principal colocaremos un control ProgressBar (en mi caso llamado pbarProgreso) y un botón (btnSinHilos) que ejecute una tarea de larga duración. Para simular una operación de larga duración vamos a ayudarnos de un método auxiliar que lo único que haga sea esperar 1 segundo, mediante una llamada a Thread.sleep().
private void tareaLarga() { try { Thread.sleep(1000); } catch(InterruptedException e) {} }
Haremos que nuestro botón ejecute este método 10 veces, de forma que nos quedará una ejecución de unos 10 segundos en total:
btnSinHilos.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { pbarProgreso.setMax(100); pbarProgreso.setProgress(0); for(int i=1; i<=10; i++) { tareaLarga(); pbarProgreso.incrementProgressBy(10); } Toast.makeText(MainHilos.this, "Tarea finalizada!", Toast.LENGTH_SHORT).show(); } });
Como veis, aquí todavía no estamos utilizando nada especial, por lo que todo el código se ejecutará en el hilo principal de la aplicación. En cuanto a la utilización del control ProgressBar vemos que es muy sencilla y no requiere apenas configuración. En nuestro caso tan sólo hemos establecido el valor máximo que alcanzará (el valor en el que la barra de progreso estará rellena al máximo) mediante el método setMax(100), posteriormente la hemos inicializado al valor mínimo mediante una llamada a setProgress(0) de forma que inicialmente aparezca completamente vacía, y por último en cada iteración del bucle incrementamos su valor en 10 unidades llamando a incrementProgressBy(10), de tal forma que tras la décima iteración la barra llegue al valor máximo de 100 que establecimos antes. Finalmente mostramos un mensaje Toast para informar de la finalización de la tarea. Pues bien, ejecutemos la aplicación, pulsemos el botón, y veamos qué ocurre.
[box style=»rounded» border=»full» icon=»none»]He colocado un pequeño vídeo al final del artículo donde puede verse el resultado final de todas las pruebas que haremos durante este tutorial. En concreto esta primera prueba puede verse entre los segundos 00:00 – 00:12[/box]
No era eso lo que esperábamos ¿verdad? Lo que ha ocurrido es que desde el momento que hemos pulsado el botón para ejecutar la tarea, hemos bloqueado completamente el resto de la aplicación, incluida la actualización de la interfaz de usuario, que ha debido esperar a que ésta termine mostrando directamente la barra de progreso completamente llena. En definitiva, no hemos sido capaces de ver el progreso de la tarea. Pero como decíamos, este efecto puede empeorar. Probemos ahora a pulsar el botón de la tarea y mientras ésta se ejecuta realicemos cualquier acción sobre la pantalla, un simple click sobre el fondo nos basta. Veamos qué ocurre ahora.
[box style=»rounded» border=»full» icon=»none»]Puedes verlo en el vídeo entre los segundos 00:13 – 00:28[/box]
Vemos cómo al intentar hacer cualquier acción sobre la aplicación Android nos ha advertido con un mensaje de error que la aplicación no responde debido a que se está ejecutando una operación de larga duración en el hilo principal. El usuario debe elegir entre esperar a que termine de ejecutarla o forzar el cierre de la aplicación. Pues bien, estos son los efectos que vamos a intentar evitar. La opción más inmediata que nos proporciona Android, al igual que otras plataformas, es crear directamente hilos secundarios dentro de los cuales ejecutar nuestras operaciones costosas. Esto lo conseguimos en Android instanciando un objeto de la clase Thread. El constructor de la clase Thread recibe como parámetro un nuevo objeto Runnable que debemos construir implementando su método run(), dentro del cual vamos a realizar nuestra tarea de larga duración. Hecho esto, debemos llamar al método start() del objeto Threaddefinido para comenzar la ejecución de la tarea en segundo plano.
new Thread(new Runnable() { public void run() { //Aquí ejecutamos nuestras tareas costosas } }).start();
Hasta aquí todo sencillo y relativamente limpio. Los problemas aparecen cuando nos damos cuenta que desde este hilo secundario que hemos creado no podemos hacer referencia directa a componentes que se ejecuten en el hilo principal, entre ellos los controles que forman nuestra interfaz de usuario, es decir, que desde el método run() no podríamos ir actualizando directamente nuestra barra de progreso de la misma forma que lo hacíamos antes. Para solucionar esto, Android proporciona varias alternativas, entre ellas la utilización del método post() para actuar sobre cada control de la interfaz, o la llamada al método runOnUiThread() para «enviar» operaciones al hilo principal desde el hilo secundario [Nota: Sí, vale, sé que no he nombrado la opción de los Handler, pero no quería complicar más el tema por el momento]. Ambas opciones requieren como parámetro un nuevo objeto Runnable del que nuevamente habrá que implementar su método run() donde se actúe sobre los elementos de la interfaz. Por ver algún ejemplo, en nuestro caso hemos utilizado el método post() para actuar sobre el control ProgressBar, y el método runOnUiThread()para mostrar el mensaje toast.
new Thread(new Runnable() { public void run() { pbarProgreso.post(new Runnable() { public void run() { pbarProgreso.setProgress(0); } }); for(int i=1; i<=10; i++) { tareaLarga(); pbarProgreso.post(new Runnable() { public void run() { pbarProgreso.incrementProgressBy(10); } }); } runOnUiThread(new Runnable() { public void run() { Toast.makeText(MainHilos.this, "Tarea finalizada!", Toast.LENGTH_SHORT).show(); } }); } }).start();
Utilicemos este código dentro de un nuevo botón de nuestra aplicación de ejemplo y vamos a probarlo en el emulador.
[box style=»rounded» border=»full» icon=»none»]Puedes verlo en el vídeo entre los segundos 00:29 – 00:43[/box]
Ahora sí podemos ver el progreso de nuestra tarea reflejado en la barra de progreso. La creación de un hilo secundario nos ha permitido mantener el hilo principal libre de forma que nuestra interfaz de usuario de actualiza sin problemas durante la ejecución de la tarea en segundo plano. Sin embargo miremos de nuevo el código anterior. Complicado de leer, ¿verdad? Y eso considerando que tan sólo estamos actualizando un control de nuestra interfaz. Si el número de controles fuera mayor, o necesitáramos una mayor interacción con la interfaz el código empezaría a ser inmanejable, difícil de leer y mantener, y por tanto también más propenso a errores. Pues bien, aquí es donde Android llega en nuestra ayuda y nos ofrece la clase AsyncTask, que nos va a permitir realizar esto mismo pero con la ventaja de no tener que utilizar artefactos del tipo runOnUiThread() y de una forma mucho más organizada y legible. La forma básica de utilizar la clase AsyncTaskconsiste en crear una nueva clase que extienda de ella y sobrescribir varios de sus métodos entre los que repartiremos la funcionalidad de nuestra tarea. Estos métodos son los siguientes:
- onPreExecute(). Se ejecutará antes del código principal de nuestra tarea. Se suele utilizar para preparar la ejecución de la tarea, inicializar la interfaz, etc.
- doInBackground(). Contendrá el código principal de nuestra tarea.
- onProgressUpdate(). Se ejecutará cada vez que llamemos al método publishProgress() desde el método doInBackground().
- onPostExecute(). Se ejecutará cuando finalice nuestra tarea, o dicho de otra forma, tras la finalización del método doInBackground().
- onCancelled(). Se ejecutará cuando se cancele la ejecución de la tarea antes de su finalización normal.
Estos métodos tienen una particularidad esencial para nuestros intereses. El método doInBackground() se ejecuta en un hilo secundario (por tanto no podremos interactuar con la interfaz), pero sin embargo todos los demás se ejecutan en el hilo principal, lo que quiere decir que dentro de ellos podremos hacer referencia directa a nuestros controles de usuario para actualizar la interfaz. Por su parte, dentro de doInBackground() tendremos la posibilidad de llamar periódicamente al método publishProgress() para que automáticamente desde el método onProgressUpdate() se actualice la interfaz si es necesario. Al extender una nueva clase de AsyncTaskindicaremos tres parámetros de tipo:
- El tipo de datos que recibiremos como entrada de la tarea en el método doInBackground().
- El tipo de datos con el que actualizaremos el progreso de la tarea, y que recibiremos como parámetro del método onProgressUpdate() y que a su vez tendremos que incluir como parámetro del método publishProgress().
- El tipo de datos que devolveremos como resultado de nuestra tarea, que será el tipo de retorno del método doInBackground() y el tipo del parámetro recibido en el método onPostExecute().
En nuestro caso de ejemplo, extenderemos de AsyncTask indicando los tipos Void, Integer y Booleanrespectivamente, lo que se traducirá en que:
- doInBackground() no recibirá ningún parámetro de entrada (Void).
- publishProgress() y onProgressUpdate() recibirán como parámetros datos de tipo entero (Integer).
- doInBackground() devolverá como retorno un dato de tipo booleano y onPostExecute() también recibirá como parámetro un dato del dicho tipo (Boolean).
Dicho esto, cómo repartiremos la funcionalidad de nuestra tarea entre los distintos métodos. Pues sencillo, en onPreExecute() inicializaremos la barra de progreso estableciendo su valor máximo y poniéndola a cero para comenzar. En doInBackground() ejecutaremos nuestro bucle habitual llamando a publishProgress() tras cada iteración indicando el progreso actual. En onProgressUpdate() actualizaremos el estado de la barra de progreso con el valor recibido como parámetro. y por último en onPostExecute() mostraremos el mensaje Toast de finalización de la tarea. Veamos el código completo:
private class MiTareaAsincrona extends AsyncTask<Void, Integer, Boolean> { @Override protected Boolean doInBackground(Void... params) { for(int i=1; i<=10; i++) { tareaLarga(); publishProgress(i*10); if(isCancelled()) break; } return true; } @Override protected void onProgressUpdate(Integer... values) { int progreso = values[0].intValue(); pbarProgreso.setProgress(progreso); } @Override protected void onPreExecute() { pbarProgreso.setMax(100); pbarProgreso.setProgress(0); } @Override protected void onPostExecute(Boolean result) { if(result) Toast.makeText(MainHilos.this, "Tarea finalizada!", Toast.LENGTH_SHORT).show(); } @Override protected void onCancelled() { Toast.makeText(MainHilos.this, "Tarea cancelada!", Toast.LENGTH_SHORT).show(); } }
Si observamos con detenimiento el código, la única novedad que hemos introducido es la posibilidad de cancelar la tarea en medio de su ejecución. Esto se realiza llamando al método cancel() de nuestra AsyncTask (para lo cual añadiremos un botón más a nuestra aplicación de ejemplo, además del nuevo que añadiremos para comenzar la tarea). Dentro de la ejecución de nuestra tarea en doInBackground() tendremos además que consultar periodicamente el resultado del método isCancelled() que nos dirá si el usuario ha cancelado la tarea (es decir, si se ha llamado al método cancel()), en cuyo caso deberemos de terminar la ejecución lo antes posible, en nuestro caso de ejemplo simplemente saldremos del bucle con la instrucción break. Además, tendremos en cuenta que en los casos que se cancela la tarea, tras el método doInBackground() no se llamará a onPostExecute() sino al método onCancelled(), dentro del cual podremos realizar cualquier acción para confirma la cancelación de la tarea. En nuestro caso mostraremos un mensaje Toast informando de ello.
[box style=»rounded» border=»full» icon=»none»]Puedes verlo en el vídeo entre los segundos 00:44 – 01:06[/box]
Mucho mejor que las alternativas anteriores, verdad? Pero vamos a mostrar una opción más. Si queremos que el usuario pueda ver el progreso de nuestra tarea en segundo plano, pero no queremos que interactúe mientras tanto con la aplicación tenemos la opción de mostrar la barra de progreso dentro de un diálogo. Android nos proporciona directamente un componente de este tipo en forma de un tipo especial de diálogo llamado ProgressDialog.
Configurar un cuadro de diálogo de este tipo es muy sencillo. Para ello vamos a añadir un botón más a nuestra aplicación de ejemplo, donde inicializaremos el diálogo y lanzaremos la tarea en segundo plano. Para inicializar el diálogo comenzaremos por crear un nuevo objeto ProgressDialog pasándole como parámetro el contexto actual. Tras esto estableceremos su estilo: STYLE_HORIZONTAL para una barra de progreso tradicional, o STYLE_SPINNER para un indicador de progreso de tipo indeterminado.
Lo siguiente será especificar el texto a mostrar en el diálogo, en nuestro caso el mensaje «Procesando…«, y el valor máximo de nuestro progreso, que lo mantendremos en 100. Por último indicaremos si deseamos que el diálogo sea cancelable, es decir, que el usuario pueda cerrarlo pulsando el botón Atrás del teléfono. Para nuestro ejemplo activaremos esta propiedad para ver cómo podemos cancelar también nuestra tarea en segundo plano cuando el usuario cierra el diálogo. Tras la configuración del diálogo lanzaremos la AsyncTask del ejemplo anterior, que tendremos que modificar ligeramente para adaptarla al nuevo diálogo. Veamos el código por ahora:
btnAsyncDialog.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { pDialog = new ProgressDialog(MainHilos.this); pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); pDialog.setMessage("Procesando..."); pDialog.setCancelable(true); pDialog.setMax(100); tarea2 = new MiTareaAsincronaDialog(); tarea2.execute(); } });
La AsyncTask será muy similar a la que ya implementamos. De hecho el método doInBackground() no sufrirá cambios.
En onProgressUpdate() la única diferencia será que actualizaremos el progreso llamando al método setProgress() del ProgressDialog en vez de la ProgressBar.
El código de onPreExecute() sí tendrá algún cambio más. Aprovecharemos este método para implementar el evento onCancel del diálogo, dentro del cual cancelaremos también la tarea en segundo plano llamando al método cancel(). Además, inicializaremos el progreso del diálogo a 0 y lo mostraremos al usuario mediante el método show().
Por último, en el método onPostExecute() además de mostrar el Toast de finalización, tendremos que cerrar previamente el diálogo llamando a su método dismiss().
Veamos el código completo de la AsyncTask modificada para usar el nuevo ProgressDialog.
private class MiTareaAsincronaDialog extends AsyncTask<Void, Integer, Boolean> { @Override protected Boolean doInBackground(Void... params) { for(int i=1; i<=10; i++) { tareaLarga(); publishProgress(i*10); if(isCancelled()) break; } return true; } @Override protected void onProgressUpdate(Integer... values) { int progreso = values[0].intValue(); pDialog.setProgress(progreso); } @Override protected void onPreExecute() { pDialog.setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { MiTareaAsincronaDialog.this.cancel(true); } }); pDialog.setProgress(0); pDialog.show(); } @Override protected void onPostExecute(Boolean result) { if(result) { pDialog.dismiss(); Toast.makeText(MainHilos.this, "Tarea finalizada!", Toast.LENGTH_SHORT).show(); } } @Override protected void onCancelled() { Toast.makeText(MainHilos.this, "Tarea cancelada!", Toast.LENGTH_SHORT).show(); } }
Si ahora ejecutamos nuestro proyecto y pulsamos sobre el último botón incluido veremos cómo el diálogo aparece por encima de nuestra actividad mostrando el progreso de la tarea asíncrona. Tras finalizar, el diálogo desaparece y se muestra el mensaje toast de finalización. Si en cambio, se pulsa el botón Atrás del dispositivo antes de que la tarea termine el diálogo se cerrará y se mostrará el mensaje de cancelación.
[box style=»rounded» border=»full» icon=»none»]Puedes verlo en el vídeo entre los segundos 01:07 – 01:35[/box]
Y con esto habríamos concluido este primer artículo sobre hilos y tareas en segundo plano. Os dejo a continuación el vídeo de demostración de la aplicación de ejemplo construida durante el tema.
Puedes consultar y/o descargar el código completo de los ejemplos desarrollados en este artículo accediendo a la página del curso en GitHub.
Demo – Hilos y AsyncTask en Android
Curso de Programación Android en PDF
¿Te ha sido de utilidad el Curso de Programación Android? ¿Quieres colaborar de forma económica con el proyecto? Puedes contribuir con cualquier cantidad, unos céntimos, unos euros, cualquier aportación será bienvenida. Además, si tu aportación es superior a una pequeña cantidad simbólica recibirás como agradecimiento un documento con la última versión del curso disponible en formato PDF. Sea como sea, muchas gracias por colaborar!
Más información:
75 comentarios
Me encanta tu tutorial y la forma en que lo explicas todo, enhorabuena ;)
Ahora una pequeña cuestión que me trae de cabeza :P Estoy trabajando con la versión 2.1 y utilizo kSoap, y me enterado que no funciona bien en las versiones superiores (4.0) porque cada llamada a Soap se debe hacer en un hilo secundario, entonces mi pregunta es la siguiente: ¿Por cada llamada Soap que realice, tengo que crear una clase AsyncTask?
Muchas gracias
Hola Alvaro, no es necesario crear una clase que extienda de AsyncTask por cada llamada al servicio web. Como has visto en este artículo tu clase AsyncTask la puedes parametrizar para que reciba distintos datos de entrada, salida y progreso, por lo que podrías crearte una AsyncTask suficientemente genérica como para que te sirva para distintos tipos de llamada al servicio. Saludos.
Gracias por hacer este tutorial!!
Muchas gracias!! Probaré a hacerlo como dices a ver si consigo resolver mi problema :D
Tengo otra pregunta, pero no es referida al tema del AsyncTask, sino a los AlertDialog, pero nadie es capaz de responderme (ni en el foro nuestro, ni buscando por internet).
Me gustaría poder poner un boton que al darle se te abra un AlertDialog (con sus botones de aceptar y cancelar) y en vez de texto tubiera un RatingBar para poder votar.
Muchas gracias por todo de nuevo compañeros :D
Álvaro, te he contestado en el foro al tema del AlertDialog.
Muchas gracias por todo Sgoliver!! Sin tu ayuda se me habría hecho muy cuesta arriba el comenzar mi Proyecto fin de carrera.
:D
MUCHISIMAS GRACIAS!!!!!!!!!
Estoy desorrollando una aplicacion y toda la informacion q compartes en tu blog me ha servido para acabarla.
sigue adelante.
y otra vez gracias
Una duda que tengo… donde puedo comprobar si el hilo ha acabado para empezar uno nuevo? He probado con esto..
hilo = new MiHiloAsincrono();
hilo.execute();
if(hilo.getStatus() == AsyncTask.Status.FINISHED)
{
Log.i(«Acabado»,»»);
}
Pero no me refleja nada. No se como tendria que comprobarlo.
Gracias de antemano.
@LuTOMetal el AsyncTask tiene dos formas de terminar, como ha dicho Salvador:
1. que termine normalmente -> se ejecuta onPostExecute()
2. que sea cancelado por el usuario -> se ejecuta onCancelled()
en ambos casos podrías poner Log.i(«Acabado»,»»)
cualquier otra solución implicaría bloquear el hilo principal (se podría hacer con un while en lugar del if que tu has puesto, pero eso haría que se bloquease)
la razón de que tu código no te refleje nada es porque justo después de que ejecutas el hilo (y éste sigue corriendo) haces la comprobación, que lógicamente da falso y por tanto no te logea nada
espero ser de ayuda :)
@Marc muchas gracias por tu respuesta :)
Hola
Fabuloso blog antes que nada. No sé si esta pregunta está especialmente relacionada con esto, pero creo que al menos es un tema parecido, ahí va:
¿Cómo puedo saber si mi aplicación ya está abierta para que cuando alguien vuelve a darle al icono recupere su estado anterior y no vuelva a abrirse sola? ¿Dejando un proceso en segundo plano? ¿Y cómo compruebo si ya se está ejecutando?
Es que estoy haciendo una aplicación para una radio online. Algo muy simple, un objeto MediaPlayer que establece la fuente y reproduce. Pero si alguien le da a menú y pulsa de nuevo la aplicación parece que se vuelve algo loca porque ya no se cierra el proceso anterior.
Espero que me puedas ayudar y enhorabuena de nuevo por tu blog.
José Manuel.
Estimado amigo, la actualización de la barra de tareas con esta tarea tan sencilla es fácil, pero cuando se está realizando un tarea como por ejemplo subir datos de un servidor, ¿como actualizas la barra durante dicho trabajo? En el ejemplo la tarea dura un segundo, pero en una tarea como la que indico no se sabe el tiempo que va a ocupar. ¿Como podría hacerse para que dentro de dicha tarea actualizase la barra cada cierto tiempo?
Hola quiero insertar en una base de datos local mientras estoy en la tarea, pero cuando quiero instanciar la base y me pide el contexto no me deja pasarle el task como contexto.
Como lo puedo resolver, desde ya muchas gracias.
Hola
Soy novato en android y necesito saber donde debo hacer la implementación de la clase que extiende de AsyncTask, si en la misma activity que la clase principal o en una nueva activity.
de antemano muchas gracias.
Estoy recibiendo clases de Android y me parece que esta forma de explicar es muchisimo mejor de las que encuentro en Ingles. Gracias.
Tengo un spinner. En la tarea BG leo un archivo de un website para cargar el ArrayAdapter del spinner. El proceso del BG lo realiza perfecto asi como la carga del spinner. Pero no tengo respuesta del spinner cuando selecciono un elemento. si retiro la tarea del BG y utilizo la misma logica pero con un archivo en el directorio raw, funciona perfectamente. Que debo modificar para que se ejecute el listener del spinner
Hola! estoy pasando un programa java a android y tengo una duda sobre la sincronizacion:
El programa es un gestor de entradas (no tiene fin practico, solo es para aprender), primero lo hice en consola y luego lo pase a gui, pero para hacerlo tuve que implementar una clase synchronized para que coordinara el programa principal y que cuando requiriera una entrada de texto parara ( wait() ) hasta que se introdujera texto y se pulsara un boton o se pulsara enter ( notify() ).
Esto en java me funciona, pero en android no… No he encontrado mucha informacion (practicamente ninguna) sobre wait()/notify() en android, no se si es que se usa otra clase nativa de android… ¿sabes algo de esto?
Gracias
Hola, excelente tu tutorial pero tengo una duda espero me puedas guiar, tengo varias clases todas estan englobadas en una sola por medio de un tabHost, cree un boton en la clase principal que es donde tengo los tabHost y por estar en esa clase al abrir las otras clases por medio de sus tabs en estas se muestra el boton que te menciono, el problema que tengo es que al presionar el boton sin importar la clase que tenga abierta pueda recopilar la informacion que tengo alamacenada en un arreglos y pasarlos a unos archivos, mi problema es que al estar el boton declarado en la clase principal al abrir otra clase que no sea la principal y presionar el boton el oyente del boton no se ejecuta y si lo presiono estando en la principal si se ejecuta pero no puede acceder a los datos de las otras clases, entonces se me ocurrio usar hilos uno en cada clase que estaran esperando a que el boton se presionado y a si poder guardar su informacion al archivo, quisiera saber si esto es posible o existe alguna otra forma de poder compartir el boton y los datos de las clases. espero me puedas ayudar, gracias.
[…] el artículo anterior del Curso de Programación Android vimos cómo ejecutar tareas en segundo plano haciendo uso de […]
Primero agradecerte toda la informacion que das en este blog.
Estoy intentando aplicar AsyncTask al ejemplo de SAX que tienes, pero en la clase que tu aquí llamas MiTareaAsincronaDialog no me reconoce las variables de mi Actividad ni siquiera el nombre de ella al intentar sacar el dialogo, me da un error donde tu pones MainHilos.
public class ObtenerFotos extends AsyncTask {
protected List doInBackground(Void… params) {
// TODO Auto-generated method stub
noticias = saxparser.parse();
return noticias;
}
@Override
protected void onPreExecute() {
RssParserSax saxparser = new RssParserSax(«http://www.europapress.es/rss/rss.aspx»);
List noticias;
}
protected void onPostExecute(List result) {
dialogo.dismiss();//lo que en el codigo llamas pbarProgreso
Toast.makeText(FotosActivity.this, «Tarea finalizada!», //FotosActivity me da error
Toast.LENGTH_SHORT).show();
}
Estoy haciendo una barbaridad? Donde estoy fallando?
Muchas gracias por anticipado.
Ya está todo solucionado. Ya me funciona y por supuesto gracias a tu curso.
He ido recopilando información de un lado y de otro y lo he conseguido.
Así que vuelvo a darte las gracias por lo buena y util que es tu página.
Gracias.
Excelente!! Tengo una pregunta para ti, OJALÁ me puedas ayudar (soy nuevo en android)… Mi AsyncTask trata de acceder a una API para comprobar la existencia de un nombre de usuario (restful web service).
Bien, he notado que tras la ejecución de un AsyncTask no se ejecuta nada posteriormente (de hecho en mi código tras comprobar el username compruebo varias cosas más). ¿Hay algo que pueda hacer?
Gracias amigo (mi correo el captain06@gmail.com)
Nada amigo!!! Ya lo he solucionado :) gracias por el post !!
[…] del servicio nos devuelve null (tremendo What The Fuck). Puedes empaparte de las tareas asíncronas aquí en el blog/curso de Salvador García Oliver, que explica todo […]
¡Muchas gracias por el tutorial!, me ha sido de gran utilidad.
Un nuevo tutorial sencillo, gracias por estos aportes!
Primero para agradecerte la información brindada, segundo quisiera saber como mostrar esta la Barra de Progreso muestras espera la respuesta de un SERVIDOR SOAP por ejemplo.
Estaría genial si cuelgas algún ejemplo de esto, o actualizas la parte de Servidores Soap.
Gracias de antemano por tu atención.
Muy bueno el blog (mi impresion buena del log la hago resumida porque a mi me rompe las pelotas la gente que para pedir algo te halaga primero importandole un carajo nada y seamos sinceros uno quiere resolver el problema que tiene. Ya te habra pasado que te preguntan ¿como estas? antes de pedirte algo Decime cuantos verdaderamente les interesa tu estado en ese momento? Creo que ninguno
Bueno voy al grano
Estoy queriendo hacer un cronometro y tome como base tu código y lo pude hacer sin ningun promemas
Pero pasa que cueando el telefono se suspende o bloquea si pasa aproximadamente mas de 1 minuto deja de funcionar en mi caso el cronometro
La pregunta en cuestion es: ¿Como puedo hacer que la aplicacion (en mi caso el cronometro) o hilo siga funcionando «en segundo plano» cuando el telefono se bloquea
Bueno te agradeceria si podrias responder a mi problema porque me esta voviendo loco y ya me estoy resignando y voy a largar todo a la mierda. jajaja
Espero con ansias tu respuesta
[…] mediante la utilización de las llamadas AsyncTask o tareas asíncronas. Más adelante dedicaremos todo un capítulo a este tema, por lo que ahora no entraremos en mucho detalle y nos limitaremos a ver cómo […]
ezequiel cuando dices se bloquea a que te refieres exactamente? a bloquear el telefono y que entre al lockscreen o que se bloquee por algun fallo de una aplicacion y quede todo congelado???
Hola sgoliver, muy buenos tutoriales.
Necesito un consejo tuyo y si tenes algo escrito sobre esto te agradeceria ejemplos.
-Tengo una base de datos externa en un servidor con SQLServer, bajo el Sist.Op. Windows y IIS7.
-Utilizo una app de android para cargar datos a esa base de datos, desarrolle una aplicacion para un 2.2 (ya que es el que tiene mi celular).
-Anda bastante bien, utilizo web service mediante Json envio parametros a un archivo externo .php el cual se encarga de conectarse y hacer consultas, ABM en la base de datos.
-El tema está( el problema) en que al instalar la app en un dispositivo con una version 4.x.x surge un error el cual detiene totalmente la aplicacion.
NOTA: para poder acceder al DB primero tenemos que pasar por el Active directory del IIS7, loguerse como usuario y a partir de ahi acceder con los datos de usuario a la DB.
He leido en tu pagina y en varios foros que el codigo funcoina porque esta en una version 2.2 o 2.3 lo cual no funcoinaria en uno 4.x.x, porque basicamente no esta hecho con AsyncTask.
También lei que para que funcione en una version superior tengo que usar AsyncTask.
Te pregunto, esto me dará la solucion con las versiones?? Podes mostrarme algo??
Muchas gracias.
P/D: agradeceria cualquier ayuda de la comunidad.
Perdon me llamo Fernando,
Agrego a lo mencionado antes, que necesariamente tengo utilizar :
JSONObject jsonObj = new JSONObject();
HttpClient client = new DefaultHttpClient();
HttpPost httpPost;
AuthScope as;
UsernamePasswordCredentials upc;
Todo para la conexion y autenticacion a la bd para luego con Json manipular los datos.
Tengo dudas respecto al tipo de los parametros de entrada de los metodos, por ejemplo en doInBackground habia estado trabajado con Void en lugar de Boolean, y en el resto de los metodos con VOid en los parametrso de entrada, que ventaja tiene hacerlo de la maneraue los trabajas?
Dejando a un lado que este blog es magnífico y me ha ayudado un montón en mi aprendizaje, me he dado cuenta de que si ejecutas varias AsyncTask al mismo tiempo, hasta que no termina la primera que se lanza no comienza la segunda y así. Vamos, que se ejecutan en serie y no en paralelo.
Leyendo la documentación de Android (http://developer.android.com/reference/android/os/AsyncTask.html) en el apartado de “Order of execution” se dice que se aplica este cambio a partir de la versión Honeycomb y se añaden unos enlaces para poder ejecutarlas en paralelo. Pues eso, aquí dejo un pedacito de código para ejecutar las AsyncTask, ahora sí, en paralelo, como un hilo de verdad ;)
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB)
{
miAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
}
else
{
miAsyncTask.execute(params);
}
Espero que le sirva de ayuda a alguien. Saludos!
Una gran ayuda soy nuevo en android y necesito programar un proceso que se ejecute cada determinado tiempo (como ser cada 5 min) desde que se instala la aplicación hasta que detenga el proceso o se des instale, que registre en mi sqlite la posición del gps en el proceso de segundo plano, y en el plano principal con la aplicación ir registrando otros datos como ser productos, clientes y ventas . hasta cierto momento trabaja bien en otros al registrar otras cosas por la aplicación me salta un error y detiene la aplicación.
estoy ocupando el ejemplo que esta en esta pagina si alguien me pudiera ayudar o tal ves otra forma de programarlo de ante manos gracias.
[…] que realice las operaciones en segundo plano utilizando un hilo secundario. El curso contiene un capitulo dedicado a describir con más detalle las tareas asíncronas o AsyncTask, por lo que en este caso […]
Hola! Muy buenos tus tutoriales! Bueno, mi problema es que me funciono todo excepto el AsyncTask. Al momento de ejecutarlo se detiene la aplicación. Tenes idea que puede ser? Gracias desde ya
Holas
Primero felicidades por el tutorial es de mucha ayuda. Espero me puedan ayudar tengo el siguiente incoveniente visual, consiste que al pasar de un Activity a otro en algunos casos desaparece el activity 1 aparece el fondo del home screen y recien aparece el activity 2, y como veran se ve horrible que se vea el fondo del screen entre actvities, esto no solia pasar antes pero implemente un new Thread(new Runnable() { public void run() {…. y runOnUiThread para unos Toast que debo lanzar … lo ideal hubiera sido usar un AsyncTask pero el codigo es algo complicado por lo cual no puedo usar el AsyncTask … ya probe de quitar el efecto entre activity mediante intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); .. la verdad nose q pasa :(
tengo un problema, cuando minimizo mi aplicacion, la tarea asincrona no se ejecuta del todo como q se queda pausada, y se acaba de ejecutar hasta q vuelvo abrir la aplicacion, y necesito q aun minimizada la tarea asincrona se ejecute por completo
Excelente explicación. hay cosas que no logro entender en otros tutoriales, recurro a este .. y LISTO..!!! ACLARADO el concepto.
Pregunta: Porque no hay una versión en vídeo ….? o si la hay y no la he visto???
Saludos desde Ecuador ( @perezjpe )
Gracias!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
[…] principal que puedan bloquear temporalmente la interfaz de usuario. Así pues, hay que crear una llamada asíncrona que lo hará en segundo plano. En resumen, lo que toca hacer ahora es lo siguiente. En el método […]
Buenísimo blog y tutoriales! Tengo una duda: Tengo un juego (Memoriator) que se ejecuta sin problemas en versiones de android 3.x e inferiores, pero en versiones superiores a la indicada (concretamente 4.x) se queda congelada. Uso AsyncTask para lanzar los niveles y he visto que da problemas para las versiones que indico. Alguna forma de solventarlo sin trastocar demasiado el código?
Cada vez que empieza un nivel nuevo, ejecuta una nueva AsyncTask mediante new IniciarNivel().execute();
Os pongo el código de la AsyncTask para que lo veáis mejor:
private class IniciarNivel extends AsyncTask {
protected Boolean doInBackground(Integer… nivel) {
publishProgress(1);
try {
Thread.sleep(4800);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
return true;
}
protected void onProgressUpdate(Integer… progreso) {
RelativeLayout botones = (RelativeLayout) findViewById(R.id.lay_botones);
// Reiniciamos Y Llenamos
llenarBotones();
// Mostramos los botones
botones.setVisibility(View.VISIBLE);
// Indicamos que memorice las parejas
TextView instrucciones = (TextView) findViewById(R.id.txtCuantas);
instrucciones.setText(R.string.txtInstrucciones1Parejiles);
}
protected void onPostExecute(Boolean correcto) {
// Ocultamos las banderas y ponemos los botones como pulsables
ocultarBotones();
}
}
He visto en otros foros que aconseja sustituir AsyncTask por: private Runnable mMyRunnable = new Runnable(){} Pero eso me lía un poco.
Muchísimas gracias por vuestra ayuda!
Hola , como puedo hacer que el celular me muestre una notificación cuando una aplicacion esta ejecutando en segundo plano cada 5 minutos por ejemplo?, espero que me puedan ayudar con esto porfavor
Hola salvador! me gusto mucho tu post, estaba buscando esto desde hace mucho pero nadie terminaba de explicarlo con manzanas y peras, hice todos tus ejemplos y si note la diferencia, me ayudaste a mejorar mucho en mi programacion, ya que tenia problemas con la velocidad de mis aplicaciones, ahora cargo bases de datos en async asi como imagenes , mis barras buscadoras son mas rapidas tambien, de hecho ahora no puedo imaginar programar sin esto. te agradezco infinitamente la molestia que te tomaste escribir todo esto… ahora que me fijo creo que no vimos nada de handlers en tu post…. pero creo que ya estan de mas.
Hola salvador, cómo puedo detectar sí el teléfono está inactivo a través de un servicio, por ejemplo para ejecutar una tarea pero solo cuando en diez minutos no haya actividad?
Gracias.
no puedo bajar el codigo en la direccion referida, no es gratuito?
https://github.com/sgolivernet/curso-android-src/tree/master/android-asynctask
Hola!!
Por lo que estuve viendo el código de la AsyncTask tu lo escribes dentro de la misma Activity, ¿no hay manera de escribir la AsyncTask en una clase aparte y así poder llamarla desde cualquier activity?
O sino hacer una clase que haga de intermediaria entre la AsyncTask y la activity, y por ejemplo, enviar el contexto de la actividad en ejecución a la AsyncTask por medio del constructor y así poder acceder a todos sus atributos y métodos (siempre que sean públicos, claro.)
Yo lo que hice fue crear una clase que extienda de AsyncTask con un constructor que reciba el contexto de donde es instanciada y lo guarde en un objeto del mismo tipo. A su vez, este constructor ejecuta el método execute() que de paso a toda la Tarea y al final cuando el hilo llegue al onPostExecute() este llama a algún método de la activity por medio de su referencia.
¿¿Que tan feo es eso?? ¿Se usan cosas como esas? ¿Es recomendable?
Bueno, no molesto más, muchas gracias.
Saludos.
Hola, ante todo gracias por los tutoriales que introdujeron al mundo de android.
Tengo un problema de hilos y gridView, no se si alguien me pueda ayudar:
tengo una cantidad(+1000) importante de vistas (texto imagen) que inflan un gridView, de una base de datos. Como son tantas vistas las levanto con hilos una por una, sin embargo surge un problema:
Cuando hago Scroll hacia abajo, muy rápido, extendido y paro en un cierto punto queda un montón de hilos todavía en ejecución y me cargan las vistas ya pasadas. Cuando esto pasa tarda mucho tiempo en ejecutar la carga de las imágenes pasadas.
Lo que realmente quiero es o cancelar los hilos que pasaron o no ejecutarlos desde el principio, necesito que cargue mi gridView solo en la posición donde me encuentro.
Gracias :D dlaya2@hotmail.com
Hola,
muy bueno tu articulo, y el siguiente, de los IntentService, tambien. Pero tengo una duda que no acabo de resolver por mas que he buscado en internet. Imagina el siguiente escenario: tengo un dispositivo que envia informacion constantemente a mi dispositivo android mediante bluetooth.
Quiero leer esa informacion todo el tiempo (mientras la actividad este visible), y mostrarla en pantalla. Y dudo mucho entre las tres aproximaciones posibles: thread, async taks y service (o intent service).
De momento siempre que he necesitado hacer una tarea larga, la tipica recuperacion de datos, he usado una async task, y efectivamente, su simplicidad es su principal argumento a favor. Pero tengo mis dudas de si es lo aconsejable para este caso, en el cual la asynctaks no finaliza por si misma, es decir, es una tarea que correria sin fin, hasta que se cancele desde fuera.
Se que tecnicamente es posible, solo me pregunto si la «best practice» en este caso es usar esta aproximacion o no.
Un saludo y enhorabuena por el blog.
Hola amigo, soy novato en android y use tu codigo.
Pero estoy teniendo un problema…
Resulta ser que, en el background llamo a una clase que obtiene un archivo de un servidor ftp y este llama a otra clase para insertar los datos obtenido a sqlite..
Al ejecutar me da el siguiente error:
05-13 01:14:00.462: E/AndroidRuntime(2518): FATAL EXCEPTION: AsyncTask #3
05-13 01:14:00.462: E/AndroidRuntime(2518): java.lang.RuntimeException: An error occured while executing doInBackground()
05-13 01:14:00.462: E/AndroidRuntime(2518): at android.os.AsyncTask$3.done(AsyncTask.java:299)
05-13 01:14:00.462: E/AndroidRuntime(2518): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
05-13 01:14:00.462: E/AndroidRuntime(2518): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
05-13 01:14:00.462: E/AndroidRuntime(2518): at java.util.concurrent.FutureTask.run(FutureTask.java:239)
05-13 01:14:00.462: E/AndroidRuntime(2518): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
05-13 01:14:00.462: E/AndroidRuntime(2518): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
05-13 01:14:00.462: E/AndroidRuntime(2518): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
05-13 01:14:00.462: E/AndroidRuntime(2518): at java.lang.Thread.run(Thread.java:856)
05-13 01:14:00.462: E/AndroidRuntime(2518): Caused by: java.lang.NumberFormatException: Invalid int: «»
05-13 01:14:00.462: E/AndroidRuntime(2518): at java.lang.Integer.invalidInt(Integer.java:138)
05-13 01:14:00.462: E/AndroidRuntime(2518): at java.lang.Integer.decode(Integer.java:157)
05-13 01:14:00.462: E/AndroidRuntime(2518): at com.bss.preventa.XmlRSincronizarDatos.obtenerClientes(XmlRSincronizarDatos.java:788)
05-13 01:14:00.462: E/AndroidRuntime(2518): at com.bss.preventa.XmlRSincronizarDatos$MiTareaAsincronaDialog.doInBackground(XmlRSincronizarDatos.java:285)
05-13 01:14:00.462: E/AndroidRuntime(2518): at com.bss.preventa.XmlRSincronizarDatos$MiTareaAsincronaDialog.doInBackground(XmlRSincronizarDatos.java:1)
05-13 01:14:00.462: E/AndroidRuntime(2518): at android.os.AsyncTask$2.call(AsyncTask.java:287)
05-13 01:14:00.462: E/AndroidRuntime(2518): at java.util.concurrent.FutureTask.run(FutureTask.java:234)
05-13 01:14:00.462: E/AndroidRuntime(2518): … 4 more
Estimado:
como lo haces para usar esta clases y sus respectivo metodos si quieres usar el paquete de JSON para hacer consultas a una base de datos, como los importa van fuera del metodo doInBackground();
por lo cual cuando declaro la variable que posee la url donde va mi consulta a sql no la ejecutara porque el metodo no detecta la libreria.
espero me puedas ayudar, ya que no he podido arrancar un segundo hilo realizando una consulta a bases de datos sql externas con el metodo este.
Atento estare a los comentarios.
Soy algo nuevo en esto de android, pero el codigo no me corre por que no encuentro donde poner el codigo :
new Thread(new Runnable() {
public void run() {
pbarProgreso.post(new Runnable() {
public void run() {
pbarProgreso.setProgress(0);
}
});
for(int i=1; i<=10; i++) {
tareaLarga();
pbarProgreso.post(new Runnable() {
public void run() {
pbarProgreso.incrementProgressBy(10);
}
});
}
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(MainActivity.this, "Tarea finalizada!",
Toast.LENGTH_SHORT).show();
}
});
}
}).start();
En que parte se pone? ya que lo pongo afuera como si fuera un metodo y el programa me marca error de que me falta un }
Ey, me ha sido de gran ayuda. Me ha ayudado mucho a entender las tareas asyncronas.!!!
Genial el Blog. 1Saludo
Hola, cuando doIn Backgroud termian su código se liberan sus recursos?
Puedo volver a llamar a la actividad sin crear otra? Qué pasa si creo otra? Gracias
Pedaso de post…
No me queda más que agradecerte por tu grandioso aporte, excelente trabajo el que realizas amigo.
Saludos.
Recien comienzo en android , no entiendo la parte de MiHilo.this de donde lo toma, o tengo que generarlo?
Carlos el «Mihilo» debes de sustituirlo por el nombre de la clase main en la que trabajas, ejemplo mi actividad principal se llama MainActivity.java, entonces en mi caso seria MainActivity.this, no se si con eso se resuelva tu duda.
Gracias, me sirve para implementar fade in y fade out, para cambio de pantalla de mi juego.
Tengo un problema en mi app y es que al llamar al método publishProgress() entra en el onProgressUpdate() por cada actualización que hago y en las últimas segun el debug de eclipse se queda dentrro del metodo onProgressUpdate y no llega a salir de este… y la app se queda como esperando algo y no da ningun error, aqui dejo el codigo de mi metodo:
protected void onProgressUpdate(Integer… params) {
super.onProgressUpdate(params);
pd.setMessage(String
.valueOf(«\n Por favor espere… »
+ (numUpdatesDone * 100) / numUpdates + «%»));
}
y en el log puedo apreciar el siguiente mensaje:
The application may be doing too much work on its main thread.
Hola! Hace tiempo estoy leyendo tu blog y no tengo mas que felicitarte, tremendo trabajo. Tengo una duda. Estoy iniciando en esto de la programación Android, y me propuse hacer una aplicación de cuentas matemáticas sencillas. Mi duda es como puedo hacer para que en una pantalla principal haya un control TextView que se valla actualizando con un valor numérico que agrego en otra activity diferente mediante un EditText? De que manera podría lograrlo? Desde ya gracias!
Un tutorial muy fácil e iinteresante que me ha aclarado bastantes dudas. Muchas gracias ^___^
Me encanta la forma en la que llevas el curso, es perfecto. Muchísimas gracias por compartir tus conocimientos.
Felicitaciones y mis sinceros agradecimientos.
muchas gracias! muy buen tutorial, muy bien explicado!
Estimado,
Excelente el post!, pero tengo aún un inconveniente. Resulta que en «mi tarea larga» en lugar de hacer un tiempo como en tu ejemplo pues realizo unas operaciones bastante complejas analizando una imagen pixel por pixel y cuando la completa no realiza los cambios que debería ver en la imagen. Quizá tenga que hacer un refresh de pantalla, o no se que…¿tienes alguna pista para darme?
Gracias
@SuppressLint(«SimpleDateFormat»)
AsyncCallWS extends AsyncTask {
String celcius = null;
@Override
protected void onPreExecute() {
resTxt.setText(«Calculando…»);
}
@Override
protected String doInBackground(String… params) {
String res = null;
if (params[0] != null && !params[0].isEmpty()) {
celcius = params[0];
res = web.getFahrenheit(celcius);
}
return res;
}
@Override
protected void onPostExecute(String result) {
resTxt.setText(result + «F»);
if (result != null && !result.isEmpty() && !result.equals(«null»)) {
ConversionBean conv = new ConversionBean(0,
new SimpleDateFormat(DataSQLite.DATE_SQLITE_FORMAT)
.format(Calendar.getInstance().getTime()),
celcius, result);
db_conv.guardarConversion(conv);
List conversiones = db_conv.listaConversiones();
for (ConversionBean c : conversiones) {
}
}
}
}
Truena al llegar al calculando, que me podrias decir que tengo mal?
Excelentes aportaciones, felicidades
Ocupo algo mas especifo de Ksoap, tendras algo?
Gracias por tus grandes aportes, valoro mucho tu trabajo y he leido y aprendido mucho con el. Tengo una duda con respecto a esta lección y es que siempre veo ejemplos donde crean la clase Async como una clase privada, ¿se puede hacer como clase publica?
De nuevo gracias
Sigo tus tutoriales y están muy bien, normalmente no me lío, pero son AsyncTask no lo tengo claro, me explico con un problema que me está ocurriendo y no doy con él.
Tengo una clase para geolocalización que puedo utilizar en varias actividades. Esta la utilizo con un método (public void activarGPS()) para obtener la latitud y la longitud. El caso es que lo que yo quería es ejecutarlo en un AsincTask. Y no se como. Mi código falla directamente en doInBackground. Te envío el parte del código por si puedes ayudarme, pues esto muy despistado, gracias de antemano por tus tutoriales.
public class GPSLocation extends AsyncTask {
…….
protected void onPreExecute() {
……..
protected String doInBackground(String… params) {
activarGPS();
Log.e(TAG, «doInBackground»);
return null;
}
protected void onProgressUpdate(Integer… prog) {
……….
protected void onPostExecute(String result) {
//Que ya veré como obtengo los datos, poco a poco primero el doInBackground
}
[…] [1] http://www.sgoliver.net/blog/tareas-en-segundo-plano-en-android-i-thread-y-asynctask/ […]
[…] Usamos Thread para que la acción se realice en segundo plano. Una explicación completa a puedes ver en la maravillosa página de sgoliver.net. […]
Hola, explicas muy bien todo, eso me agrada, hace mucho más fácil entender todo cuando estás aprendiendo, de esta manera se hace más sencillo implementar las funciones de android, pero me gustaría saber como puedo hacer que mi app realice cada cierto una acción incluso aunque la app no este abierta o que el móvil este en modo de espera y que muestre notificaciones. Espero puedan orientarme un poco al respecto. Saludos!
Muchas Gracias, Doc, me ayudaste bastante con tu explicación, ya que me sirvio para definir que un asynctask solo se puede utilizar para hilos que contengan Objetos de la Interfaz de Usuario, lo demás se puede utilizar con thread, muchas por tu explicacion.
Que bien explicado. Quedó clarisimo. Muy buen ejemplo.
Saludos, gracias.