Tareas en segundo plano AsyncTask Thread

Documentos relacionados
Concurrencia en Android LSUB, GYSC, URJC

Ejecución de hebras. En realidad, todas las aplicaciones escritas en Java son aplicaciones multihebra (recuerde el recolector de basura).

Hilos - Ejercicios. Índice

Concurrencia en Android LSUB, GYSC, URJC

Arquitecturas cliente/servidor

Android TAG y el principio DRY

Tema 6. Threads: programas multitarea

PROGRAMACIÓN EN JAVA. { una línea para definir, crear o ejecutar ; }

Laboratorio I Java Threads (Silberschatz Galvin)

Desarrollo de Aplicaciones para Android

Que es un Android Intent?

Guillermo Román Díez

Normalmente, los programas son ejecutados de forma secuencial. Único flujo de control

Programación concurrente

Threads o Hilos. Un thread en JAVA comienza como una instancia de java.lang.thread antes de convertirse en un hilo de ejecución.

Programación concurrente en Java

Manejadores en Android LSUB, GYSC, URJC

Programación multimedia y dispositivos móviles. Servicios Web

Android avanzado. Sesión 5: Notificaciones. Experto en Desarrollo de Aplicaciones para Dispositivos Móviles

Anexo. Control de errores

UPM Concurrencia en Java

2. Indica cuál de las siguientes afirmaciones es cierta:

Tema 4. Control de flujo. Programación Programación - Tema 4: Control de Flujo

Unidad Didáctica 3. Tipos genéricos. Fundamentos de Programación Departamento de Lenguajes y Sistemas Informáticos

Tema 12: Programación multihilo

Programación concurrente Hebras

Unidad IV: Programación concurrente (MultiHilos) 4.1. Concepto de hilo

Ejercicios - Servicios

BENEMERITA UNIVERSIDADD AUTONOMA DE PUEBLA FACULTAD DE CIENCIAS DE LA COMPUTACIÓN LICENCIATURA EN CIENCIAS DE LA COMPUTACIÓN

Android avanzado. Índice. Hilos Hilos de ejecución...3. Sincronización de hilos Hilos e interfaz de usuario Hilos - Ejercicios...

Universidad Autónoma de Baja California Facultad de Ingeniería Apuntes de Programación Orientada a Objetos I

Programación concurrente en Java. Breve introducción. Miguel Ángel LATRE Dept. de Informática e Ingeniería de Sistemas

TP Nº4 Android - SQLite Fecha Miércoles 2013/08/14 Profesor: Pablo Ulman (Polshu).

Sebastián García Galán

Examen parcial Convocatoria de junio de 2005 FUNDAMENTOS DE LA PROGRAMACIÓN

ALMACENAMIENTOS DE DATOS EN ANDROID CON SQLITE

Ejemplo. class SiNoThread extends Thread { private String SiNo; static int Contador = 0; public SiNoThread(String s) { super(); SiNo = s; }

Servicios - Ejercicios

Notificaciones y AppWidgets - Ejercicios

Servicios LSUB, GYSC, URJC

Servicios Web Android

Variables. Una variable no es más que un nombre simbólico que identifica una dirección de memoria: vs.

Ejercicio 3. Manejo de la Vista y Eventos en Android Ejercicio 3 Curso de Android con Java Derechos Res Dere e c rvados hos Res Gl e obal rva

Práctica 3. Android. Tutorial appfotovoz

Estructuras de control selectivas

Experto en Desarrollo de Aplicaciones para Dispositivos Móviles Android avanzado

Ejercicio 16. Mejora de Notificaciones en Android. Android Con Java. Ejercicio 16. Mejora de Notificaciones en Android. Curso de Android con Java

BENEMERITA UNIVERSIDAD AUTONOMA DE PUEBLA FACULTAD DE CIENCIAS DE LA COMPUTACIÓN LICENCIATURA EN CIENCIAS DE LA COMPUTACIÓN

CODIGO PROYECTO: AppPixelproServicioWeb Proyecto Android - Servicio Web

Introducción a los Threads Java

MANIPULACIÓN DE VISTAS (VIEW)

UNIDAD III.- Programación Concurrente

Construcciones del Lenguaje Java

Importar y exportar aplicaciones Para importar proyectos de Android a Android studio

Tema 2.- Objetos y mensajes

Colas. 5.1 Implementación

import java.applet.*; import java.awt.*; import java.awt.event.*;

EXCLUSIÓN MUTUA ENTRE HILOS. TEMA 5: Control de la Concurrencia en Java (API Estándar) Sintaxis para Bloques de Código Sincronizado

TEMA 5: Control de la Concurrencia en Java (API Estándar)

HERENCIA (2ª parte) En Java todas las clases derivan de otra, aunque no se diga explícitamente.

PROGRAMACIÓN ORIENTADA A OBJETOS 10/02/2009. Examen de Java. Nombre: DNI: Titulación:

Concurrencia Monitores. Guillermo Román Díez

Ejercicios - Menús, listas y barras de progreso

Sincronización por Colas en en Java

Multitarea en Java. Rafa Caballero - UCM

Java Threads. Sistemas Distribuidos Rodrigo Santamaría

Unidad Didáctica 2. Elementos básicos del lenguaje Java Tipos, declaraciones, expresiones y asignaciones

Diseño de tipos Igualdad, representación, código, copia y relación de orden

Ejercicio 20. SQLite en Android. Android Con Java. Ejercicio 20. Uso de SQLite en Android. Curso de Android con Java

INTRODUCCIÓN.

Algoritmos y Estructuras de Datos Tema 2: Diseño de Algoritmos

1. Fundamentos. Existen dos tipos distintos de multitarea: BASADA EN PROCESOS

Centro Asociado Palma de Mallorca. Antonio Rivero Cuesta

Programación orientada a objetos III

FUNDAMENTOS DE PROGRAMACIÓN. SEPTIEMBRE 2007.

PROGRAMACIÓN ORIENTADA A OBJETOS 1/7/2009. Examen de Java. Nombre: DNI: Titulación:

Ejercicio 4. Manejo de Layouts en Android. Android Con Java. Ejercicio 4. Manejo de Layouts en Android. Curso de Android con Java

Unidad V. Ya veremos qué poner en "algunas_palabras" y "algo_más", por ahora sigamos un poco más.

Programación orientada a objetos. Resumen de Temas Unidad 5: Herencia

Natalia Partera Jaime Alumna colaboradora de la asignatura

UPM Tareas de tiempo real en RT Java

Estructura de Datos Unidad 1: Repaso del Lenguaje Java

Tema 2: Aplicaciones Multihilo, Cliente Servidor

Programación Orientada a Eventos

Procesamiento paralelo con hilos de Java

Tema III. Multihilo. Desarrollo de Aplicaciones para Internet Curso 12 13

Ingeniería del Software Separación entre Presentación y Lógica del Negocio

Programando para Android: una sencilla aplicación

Tema 2: Programación basada en Objetos

PRACTICAS DE ANDROID 12 - Lanzar un segundo "Activity" y pasar parámetros Problema:

Scala Actors Tutorial Breve

CAPÍTULO 3. PROCESOS VS. HILOS

Servlet 3.0 (II) Servlets Asincronos

Ejercicio 18. Configuración de Widgets en Android. Android Con Java. Ejercicio 18. Configuración de Widgets en Android. Curso de Android con Java

Android y Recursos. Android R.java (fichero)

MONITORES EN JAVA. Antonio Tomeu Control de la Concurrencia en Java: API Estándar

ELO330: Programación de Sistemas: Certamen Final 8/11/2006 Certamen Final 100 minutos. Puede usar Apuntes. Todas las preguntas tienen igual puntaje.

Parte I: Programación en un lenguaje orientado a objetos

dit UPM Tema 2: Concurrencia /threads (java) Análisis y diseño de software José A. Mañas

Patricio Olivares. 25 de abril de 2017

Transcripción:

Tareas en segundo plano AsyncTask Thread Programació De Dispositius Mòbils PRDM Cristobal Raya Giner 2015

Hilos de ejecución En una aplicación Android, todas las actividades, los servicios y los broadcast receivers se ejecutan en el mismo hilo de ejecución, el llamado hilo principal, main thread, o GUI thread. Un hilo de ejecución se puede definir de forma simple como un conjunto de procesos con diferentes tareas que se ejecutan consecutivamente. Con un solo hilo, los procesos han de ejecutarse secuencialmente, y en caso de que uno de ellos ocupara un tiempo excesivamente largo, podría llegar hasta bloquear la ejecución. Hilo principal Ejecución de los Procesos 5 s 30 s 15 s 20 s 5 + 30 + 15 + 20 = 70 s Para reducir el tiempo de ejecución y principalmente reducir la posibilidad del bloqueo de la ejecución, se utiliza la multitarea que permite ejecutar varios hilos simultáneamente y ejecutar simultáneamente varios procesos. El sistema Android monitoriza las operaciones realizados en el hilo principal y detecta aquellas que superen los 5 segundos, y avisa con el mensaje Application Not Responding que permite decidir al usuario si esperar o forzar el cierre de la aplicación. Hilos multitarea Los hilos multitarea, también se conocen como tareas en segundo plano o hilos secundarios. De esta forma se ejecutan varios procesos a la vez y en caso de que uno de ellos pueda llegar a bloquearse, no tiene por qué afectar a los demás procesos. tiempo proceso más largo 30 s Hilo principal Hilo 1 Hilo 2 Hilo 3 Hilo 4 5 s 30 s 15 s 20 s

Para realizar tareas en segundo plano, el sistema Android proporciona principalmente dos alternativas: Crear directamente un nuevo hilo para ejecutar las tareas mediante las clases Thread y Handler que proporciona java (java.lang.thread) Utilizar la clase auxiliar AsyncTask de Android (android.os.asynctask<params, Progress, Result>) El problema que aparece al trabajar con hilos secundarios es que no se puede hacer referencia directa a componentes del hilo principal desde los hilos secundarios. Por ejemplo no podríamos actualizar el valor de un TextView del hilo principal desde el hilo secundario. Pero existen varias alternativas para solucionarlo en función del tipo de hilo, entre ellas el uso de Handler o runonuithread() en Threads, o el uso publishprogress() y onprogressupdate() en AsynTask. Las recomendaciones de uso de Threads o AsynTask, son entre otras: Thread: Operaciones de red que requieran de moderada a gran cantidad de datos, como descargas y subidas de datos Tareas que requieran un alto uso de la CPU Tareas en que sea necesario controlar el uso de la CPU respecto al hilo principal Necesita el uso de Handlers para comunicarse con el hilo principal (UI Thread) AsyncTask: Operaciones simples de red que no requieran gran cantidad de datos Tareas sobre disco que requieran pocos milisegundos Facilita la comunicación con el hilo principal y no es necesario el uso de Handlers. Utiliza más tiempo de CPU que Thread Thread La clase Thread es la clase que proporciona java (java.lang.thread) que nos permite ejecutar hilos secundarios. Los hilos no comparten información con la GUI principal directamente, y es necesario utilizar intermediarios. Para ello podemos utilizar varias alternativas, como el uso de objetos Handler o el método runonuithread(), que se encargarán de compartir la información con el hilo principal. Una de las métodos más rápidos es utilizar la interfície runnable(), que implementará el método run(), y dentro del método se ejecutará el código correspondiente a la comunicación entre el Thread secundario y el hilo principal. Como alternativa se puede utilizar el objeto Handler, y utilizar su método post() donde mediante la interfície Runnable() también puede comunicarse con el hilo principal.

Una vez creado el Thread, se ha de activar mediante el método start(). El siguiente ejemplo crea un Thread en el método oncreate() de la actividad, y modifica el texto de dos TextView, uno mediante Handler.post() y otro mediante runonuithread(). public class MainActivity extends AppCompatActivity { TextView mensajepost, mensajeonui; Handler mensajehandler=new Handler(); String msgstring; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); mensajepost=(textview) findviewbyid(r.id.textview); mensajeonui=(textview) findviewbyid(r.id.textview2); new Thread(new Runnable() { msgstring="mensaje del Thread a través de "; mensajehandler.post(new Runnable() { mensajepost.settext(msgstring+"post"); ); runonuithread(new Runnable() { mensajeonui.settext(msgstring+"runonuithread"); ); ).start(); Para una mejor organización disminuyendo el código insertado en oncreate(), es aconsejable crear el Thread como una nueva clase extensión de Thread y después en oncreate() crear un objeto de dicha clase. public class MainActivity extends AppCompatActivity { TextView mensajepost, mensajeonui; String msgstring; Handler mensajehandler=new Handler(); Hilosecundario hilo; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate);

setcontentview(r.layout.activity_main); mensajepost=(textview) findviewbyid(r.id.textview); mensajeonui=(textview) findviewbyid(r.id.textview2); hilo=new Hilosecundario(); hilo.start(); private class Hilosecundario extends Thread{ msgstring="mensaje del Thread a través de "; mensajehandler.post(new Runnable() { mensajepost.settext(msgstring+"post"); ); runonuithread(new Runnable() { mensajeonui.settext(msgstring+"runonuithread"); ); Otro ejemplo en que continuamente está ejecutándose de cálculo de rotación y este se aplica a dos TextView public class MainActivity extends AppCompatActivity { TextView mensajepost, mensajeonui; float rotacion=0; Handler mensajehandler=new Handler(); Hilorotacion hilo; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); mensajepost=(textview) findviewbyid(r.id.textview); mensajeonui=(textview) findviewbyid(r.id.textview2); hilo=new Hilorotacion(); hilo.start(); private class Hilorotacion extends Thread{ while(true){ try{ Thread.sleep(1000); catch (InterruptedException e){ rotacion=rotacion+45; if (rotacion==360) {rotacion=0; mensajehandler.post(new Runnable() { mensajepost.settext("post Rotacion:" +Float.toString(rotacion)); mensajepost.setrotation(rotacion); ); runonuithread(new Runnable() {

); mensajeonui.settext("runonuithread Rotacion: " +Float.toString(360-rotacion)); mensajeonui.setrotation(360-rotacion); Para no tener que utilizar la interfície Runnable() se pueden utilizar los mensajes del objeto Handler, mediante los cuales el hilo principal puede decidir qué hacer con ellos. Habiendo creado un Handler, en el Thread se envía un mensaje mediante el método obtainmessage() y sendtotarget() del Handler. En él se envía quien ha enviado el mensaje y el mensaje: Handler.obtainMessage(int what, Object obj).sendtotarget(); Aunque también se pueden enviar dos argumentos más de forma opcional Handler.obtainMessage(int what, int arg1, int arg2, Object obj).sendtotarget(); En el hilo principal se inicia el Thread, y se crea el Handler. En el Handle se añade el método handlemessage(msg) con el que se gestionarán los mensajes recibidos del Thread, utilizando los argumentos enviados por el Thread. import android.os.message; public class MainActivity extends AppCompatActivity { TextView txt1,txt2; Handler intermediario; private Hilosecundario Hilomsg; final int mensaje1=1; final int mensaje2=2; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); txt1=(textview) findviewbyid(r.id.textview); txt2=(textview) findviewbyid(r.id.textview2); Hilomsg = new Hilosecundario(); Hilomsg.start(); intermediario = new Handler(){ public void handlemessage (Message msg){ if (msg.what==mensaje1){ String leemsg1 = (String) msg.obj; txt1.settext(leemsg1); if (msg.what==mensaje2){ String leemsg2 = (String) msg.obj; txt2.settext(leemsg2); ;

private class Hilosecundario extends Thread{ int contador=0; String msg1="mensaje 1: "; String msg2="mensaje 2: "; while (true){ try{ intermediario.obtainmessage(mensaje1,msg1+integer.tostring(contador)).send ToTarget(); Thread.sleep(500); contador++; intermediario.obtainmessage(mensaje2,msg2+integer.tostring(contador)).send ToTarget(); Thread.sleep(500); contador++; catch (InterruptedException e){ break; Utilizar la clase Thread de Java puede ser un poco complejo de interpretar, aunque es el método recomendado para tratar gran cantidad de datos y para tareas complejas. En caso de necesitar tareas sencillas y con pocos datos, en Android podemos utilizar la clase AsyncTask. AsyncTask La clase AsyncTask que proporciona Android, permite realizar tareas e interactuar con el hilo principal igual que con Thread, pero de una forma más organizada y sin el uso de Handlers ni runonuithread(). Al crear una instancia de la clase AsyncTask se necesitan definir tres tipos de datos genéricos: Los tres tipos necesarios son: android.os.asynctask<params, Progress, Result> Parámetros (Params). El tipo de los parámetros que recibirá como entrada tarea en segundo plano en ejecución (doinbackground()) Progreso (Progress). El tipo utilizado durante la tarea en segundo plano para indicar el progreso que se recibirá como parámetro en el método onprogressupdate() y que se incluirá como parámetro en el método publishprogress() Resultado (Result). El tipo que se devolverá como resultado al finalizar la tarea, que será el tipo retornado por doinbackground() y recibido por onpostexecute() Si alguno de los tipos no son necesarios, se pueden definir del tipo Void: private class MyTask extends AsyncTask<Void, Void, Void> {...

La clase está organizada en diferentes métodos en función del estado de la tarea: onpreexecute(): Se ejecutará antes del código principal de la tarea y se utilizará normalmente para inicializar y preparar la ejecución de la tarea doinbackground(): Ejecuta el código principal de la tarea onprogressupdate(): Se ejecuta cada vez que llamemos al método publishprogress() desde el método doinbackground() onpostexecute(): Se ejecuta al finalizar la tarea, al finalizar el método doinbackground() oncancelled(): Se ejecutará al cancelar la ejecución de la tarea antes de la finalización normal private class TareaAsyncTask extends AsyncTask <Byte,Integer,Long> { protected void onpreexecute() { super.onpreexecute(); protected Long doinbackground(byte... params) { return null; protected void onprogressupdate(integer... values) { super.onprogressupdate(values); protected void onpostexecute(long along) { super.onpostexecute(along); protected void oncancelled(long along) { super.oncancelled(along); La siguiente figura expresa de forma gráfica la ejecución de una tarea con AsyncTask onpreexecute() onprogressupdate() onpostexecute() publishprogress() doinbackground() oncancelled() La tarea se inicia con el método AsyncTask.execute (), y se puede cancelar con AsyncTask.cancel ()

En el siguiente ejemplo se utilizará un AsynTask para incrementar un contador en el intervalo de tiempo indicado. En el layout se utilizarán un TextView para mostrar el valor, un EditText para introducir el valor del intervalo, un botón para iniciar la tarea y otro para cancelarla. Al pulsar el botón de inicio, si la tarea no está activa, se creará la tarea enviando el intervalo de tiempo cuando se ejecute mediante Tarea.execute(intervalo). Este intervalo lo recibirá la tarea AsyncTask mediante el tipo params. Al pulsar el botón de cancelar se cancela la ejecución y elimina la tarea, pero al indicar false en la cancelación (Tarea.cancel (false)), deja que finalice la ejecución del código. En la creación de la tarea se utilizarán todos los tipo (Params, Progress, Result). En el método onpreexecute() de inicializaciones se creará un String con la parte inicial del mensaje. En el código principal de la tarea de doinbackground(), realizará un retardo con el intervalo que envió el hilo principal al executar la tarea, recibido como parámetro. Creará el mensaje y enviará al método onprogressupdate() mediante publishprogress(). Al poder cancelarse la tarea, es necesario comprobar si se ha cancelado para no continuar la ejecución, ya que en caso se cancelar y continuar la ejecución aparecería un error. Finalmente envía el valor del contador al método oncancelled(). En onprogressupdate() recibe el valor del contador enviado por doinbackground(), mediante publishprogress(), y modifica el texto del hilo principal. En oncancelled() recibe el último valor del contador al finalizar doinbackground(), y muestra un Toast. El método onpostexecute() no realiza nada ya que al haber un bucle infinito en el código de doinbackground(), nunca dejará este de ejecutarse y onpostexecute() no ejecutará nunca ningún código. public class MainActivity extends AppCompatActivity { Button inicio,cancela; TextView texto; EditText retardo; Boolean tareaactiva=false; Integer contador=0; Integer espera; String mensaje; TareaSincrona Tarea; protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate);

setcontentview(r.layout.activity_main); inicio=(button) findviewbyid(r.id.iniciar); cancela=(button)findviewbyid(r.id.cancela); texto=(textview)findviewbyid(r.id.textview); retardo=(edittext)findviewbyid(r.id.retardoms); inicio.setonclicklistener(new View.OnClickListener() { public void onclick(view v) { if (tareaactiva==false){ espera=integer.parseint(retardo.gettext().tostring()); Tarea=new TareaSincrona(); Tarea.execute(espera); tareaactiva=true; ); cancela.setonclicklistener(new View.OnClickListener() { public void onclick(view v) { if (tareaactiva==true){ Tarea.cancel(false); //false deja finalizar la tarea Tarea=null; tareaactiva=false; ); private class TareaSincrona extends AsyncTask <Integer,String, Integer>{ protected void onpreexecute() { mensaje="contador: "; protected Integer doinbackground(integer... params) { while (true){ SystemClock.sleep(params[0]); contador++; String msg=mensaje+integer.tostring(contador); publishprogress(msg); //Envia a onprogressupdate() if(iscancelled()) break; // NECESARIO si se cancela!!! return contador; //Envia a oncancelled() y onpostexecute() protected void onprogressupdate(string... values) { texto.settext(values[0]); //Recibe de doinbackground() protected void onpostexecute(integer integer) { //Como el código del método doinbackground contiene un bucle //infinito, no dejará de ejecutarse nunca de forma normal protected void oncancelled(integer integer) { String ultimocnt=integer.tostring(integer); //Recibe de doinbackground() Toast.makeText(MainActivity.this, "Tarea cancelada! Contador: "+ultimocnt,toast.length_long).show();