Tema 4.9 Hebras

51
Análisis y Diseño de Software Departamento de Ingeniería de Sistemas Telemáticos http://moodle.dit.upm.es Hebras Carlos A. Iglesias <[email protected]> v1.0 22/04/2013

Transcript of Tema 4.9 Hebras

Page 1: Tema 4.9 Hebras

Análisis y Diseño de Software

Departamento de Ingeniería de Sistemas Telemáticoshttp://moodle.dit.upm.es

Hebras

Carlos A. Iglesias <[email protected]>

v1.0 22/04/2013

Page 2: Tema 4.9 Hebras

Hebras 2

Temario● 4.1 Introducción a Android ● 4.2 Introducción Desarrollo con Android

● 4.3 Ejemplo Desarrollo y Depuración ● 4.4 Actividades● 4.5 Interfaces de Usuario

● 4.6 Intenciones● 4.7 Acceso a Datos● 4.8 Preferencias● 4.9 Hebras

Page 3: Tema 4.9 Hebras

Hebras 3

Teoría

Ejercicio práctico en el ordenador

Ampliación de conocimientos

Lectura / Vídeo / Podcast

Práctica libre / Experimentación

Leyenda

Page 4: Tema 4.9 Hebras

Hebras 4

● Android Developers

Bibliografía

http://developer.android.com/guide/components/processes-and-threads.html

Page 5: Tema 4.9 Hebras

Hebras 5

Objetivos

● Entender cómo podemos manejar hebras y concurrencia con android

● Revisar los conceptos aprendidos de concurrencia

Page 6: Tema 4.9 Hebras

Hebras 6

Hebras en Android

● Android se basa en Linux, por lo que utiliza el sistema de gestión de hebras de linux

● Vamos a ver cómo usar las hebras al programar en Android

Page 7: Tema 4.9 Hebras

Hebras 7

Ejecución Monohebra

● Por defecto, una aplicación Android ejecuta sólo una hebra (single thread):– Cada instrucción se ejecuta, una a

continuación de otra– Cada llamada es bloqueante– La hebra que se ejecuta es la hebra de interfaz

de usuario (UI thread), es responsable de 'pintar' y de capturar los eventos del usuario

– Ejecución monohebra:

Page 8: Tema 4.9 Hebras

Hebras 8

¿Qué pasa si se cuelga una actividad?

● El sistema operativo está 'atento', y si una actividad no responde (normalmente 5 segundos), nos avisa para que 'la matemos'– Diálogo ANR (Application Not Responding)

Page 9: Tema 4.9 Hebras

Hebras 9

Problema monohebra: bloqueo UI

Solución: usamos hebras

Page 10: Tema 4.9 Hebras

Hebras 10

Ejemplo

● Una aplicación que se descarga un fichero

Android in Practice, Collins et al., 2011,Cap 6, Manning. Ejemplo disponible en http://www.manning.org/collins

Page 11: Tema 4.9 Hebras

Hebras 11

Interfaz main.xml (I)

Page 12: Tema 4.9 Hebras

Hebras 12

Interfaz main.xml (II)

Page 13: Tema 4.9 Hebras

Hebras 13

Actividad: SimpleImageDownload (I)

Creo un objeto 'Runnable' para descargar la imagen

Page 14: Tema 4.9 Hebras

Hebras 14

Actividad: SimpleImageDownload (II)

Al pinchar el botón, creo una hebra con el objeto Runnable y ejecuto start()

Page 15: Tema 4.9 Hebras

Hebras 15

Para ver si ha terminado... trazas

Page 16: Tema 4.9 Hebras

Hebras 16

Podemos depurar para ver las hebras

Proceso del sistema

Nuestro proceso1. Click – Selecciono proceso

2. Depurar

3. Depurar hebras

4. Ver hebras (actualizar)

Page 17: Tema 4.9 Hebras

Hebras 17

Nuestra hebra

UI Thread

Page 18: Tema 4.9 Hebras

Hebras 18

Análisis

● ¿Cuánto vive la hebra?– Termina cuando termina el método run(). Puede

terminar más tarde que la Actividad / Servicio que lo inició → No debería tener referencias a estos objetos, puede darnos problemas

● Es una 'mala solución' – No podemos indicar en la interfaz que hemos terminado

● ¿Qué pasa si damos muchas veces al botón? → Generamos muchas hebras...

Page 19: Tema 4.9 Hebras

Hebras 19

Soluciones

● Problemas para actualizar UI desde la hebra– Creamos varias hebras (la UI y otras) y las

comunicamos: Handler

● Problemas si piden muchas hebras– Creamos un 'pool' de hebras y sólo tenemos

ese número activo– Así además reutilizamos las hebras y no hace

falta crearlas cada vez: ThreadPoolExecutor

Page 20: Tema 4.9 Hebras

Hebras 20

Ejecución multihebra

● Separamos tareas 'que tardan mucho' en diferentes hebras

● Así, simulamos mayor paralelismo, y la interfaz responde sin penalizaciones

● Casos normales de una hebra:– Un servicio de actualización que se ejecuta de

fondo (background) – Un calculo que lleva mucho tiempo– Almacenamiento de datos en tarjeta SD

Page 21: Tema 4.9 Hebras

Hebras 21

¿Cómo programamos esto en Android?

● Definiendo un servicio que se ejecuta de fondo y envía notificaciones a la interfaz (lo veremos, es la 'opción mejor')

● Usando una hebra (thread) de fondo– Usando la clase Thread y Handler directamente

• Las hebras no pueden notificar directamente a la hebra de interfaz UI

– Usando la clase AsyncTask, que facilita ejecutar tareas de fondo y publicar resultados en la hebra UI principal

Page 22: Tema 4.9 Hebras

Hebras 22

Hebras

● En Android, tenemos una hebra principal, la UIThread, que es responsable de la interfaz

● Esta hebra puede crear otras hebras secundarias que NO pueden acceder a la interfaz

● La comunicación entre la hebra ppal y las secundarias se hace con un Handler

Page 23: Tema 4.9 Hebras

Hebras 23

Handler

● Al comunicarnos con la hebra principal con un Handler, podemos hacer dos cosas:– Intercambiar mensajes de la cola de mensajes

del Handler– Pasar objetos Runnables para que los ejecute

la hebra principal

http://developer.android.com/reference/android/os/Handler.html

Page 24: Tema 4.9 Hebras

Hebras 24

Comunicación hebras Mensajes

<<Thread>>Hebra principal (UI)

Handler h

<<Thread>>Hebra secundaria 1

<<Thread>>Hebra secundaria 1

<<Runnable>>Runnable1

1. Message msg = h.obtainMessage()

2. h.sendMessage(msg)

handleMessage(Message msg)

Constructor con patrón de diseño

Factoría para reutilizar objetos

Page 25: Tema 4.9 Hebras

Hebras 25

Esquema paso mensajes

HebraPrincipal extends Activity {private Handler h = new Handler() {public void handleMessage(Message msg) {

// procesa mensajes}

metodo() { // crea una hebra secundaria Thread th = new Thread(new Runnable(){ // método de la hebra secundaria ... Message msg = h.obtainMessage(); h.sendMessage(msg); ... }); } }

Page 26: Tema 4.9 Hebras

Hebras 26

Comunicación hebrasCola de Tareas

<<Thread>>Hebra principal (UI)

Handler h

<<Thread>>Hebra secundaria 1

<<Thread>>Hebra secundaria 1

<<Runnable>>Runnable r2

h.post(r1)

h.postAtFrontOfQueue(r2)

<<Runnable>>Runnable r1

Page 27: Tema 4.9 Hebras

Hebras 27

Esquema paso tareasHebraPrincipal extends Activity {

private Handler h = new Handler() {public void onCreate() {

…Thread th = new Thread(r2, “Background”);th.start();

}private Runnable r1 = new Runnable() {

public void run() {// actualizo UI

}}private Runnable r2 = new Runnable() {

public void run() {// ejecuto cosash.post(r1);

}}

}

Page 28: Tema 4.9 Hebras

Hebras 28

Más detalle

Sólo el thread principal tiene un objeto Looper, a través del que

accede a la cola de mensajes en un bucle

Page 29: Tema 4.9 Hebras

Hebras 29

Ejemplo con mensajes

● Vamos a hacer una aplicación que vaya mostrando el progreso de la tarea de fondo

● Usaremos ProgressBar

Page 30: Tema 4.9 Hebras

Hebras 30

Interfaz main.xml (I)

Page 31: Tema 4.9 Hebras

Hebras 31

Interfaz main.xml (II)

Page 32: Tema 4.9 Hebras

Hebras 32

Actividad (I)

Page 33: Tema 4.9 Hebras

Hebras 33

Actividad (II)

Page 34: Tema 4.9 Hebras

Hebras 34

Actividad (III)

Page 35: Tema 4.9 Hebras

Hebras 35

Ejecución

Page 36: Tema 4.9 Hebras

Hebras 36

Ejemplo paso de tareas

Page 37: Tema 4.9 Hebras

Hebras 37

main.xml

Page 38: Tema 4.9 Hebras

Hebras 38

Actividad (I)

Page 39: Tema 4.9 Hebras

Hebras 39

Actividad (II)

Page 40: Tema 4.9 Hebras

Hebras 40

Actividad (III)

Page 41: Tema 4.9 Hebras

Hebras 41

Usando AsyncTask

● Usar las hebras directamente es tedioso

● Android proporciona AsyncTask– Permite crear una hebra de fondo que publica

en la hebra UI sin tener que programar Threads o Handlers

– Definimos una tarea 'asíncrona' que se ejecuta de fondo y publica sus resultados en la hebra UI

Page 42: Tema 4.9 Hebras

Hebras 42

AsyncTask – Uso básico● Hebras: UI Thread (UITh) y Background Thread

(BGTh, la AsyncTask) ●Tipos genéricos: Params, Progress, Result● Estados principales

– onPreExecute (UITh)– doInBackground (BGTh)– onProgressUpdate(UITh)– onPostExecutre(UITh)

● Método auxiliar– publishProgress (BGTh)

Page 43: Tema 4.9 Hebras

Hebras 43

AsyncTask

● Una AsyncTask tiene 3 tipos genéricos● AsyncTask<Params, Progress, Result>

– Params – tipo de parámetros enviados a la tarea para su ejecución

– Progress – tipo de las unidades de progreso publicadas durante su ejecución

– Result – resultado de la ejecución de la tarea

● Si no usamos un tipo, lo ponemos Void (con V)

Page 44: Tema 4.9 Hebras

Hebras 44

Métodos de AsyncTask● onPreExecute(): invocado por UIth

justo tras ejecutar la tarea

● doInBackground(Params) – invocado por BGTh justo tras onPreExecute

● onProgressUpdate(Progress) – invocado por UITh tras una llamada de BGTh a publishProgress(Progress)

● onPostExecute(Result) invocado por UITh justo tras terminar BGTh

Page 45: Tema 4.9 Hebras

Hebras 45

Ejemplo AsyncTask

Page 46: Tema 4.9 Hebras

Hebras 46

Interfaz main.xml

Page 47: Tema 4.9 Hebras

Hebras 47

Actividad MainTask

Page 48: Tema 4.9 Hebras

Hebras 48

Actividad MainTask (II)

… → número de argumentos

variable, se procesa como un array

Page 49: Tema 4.9 Hebras

Hebras 49

Actividad MainTask (III)

Page 50: Tema 4.9 Hebras

Hebras 50

Resumen

● En este tema hemos aprendido a gestionar concurrencia con tareas de fondo en Android

● Hemos visto cómo gestionar directamente hebras, comunicarlas con Handlers, y cómo usar AsyncTasks

● Por último, cómo darle un mejor aspecto visual y crear recursos alternativos

Page 51: Tema 4.9 Hebras

Hebras 51

¿Preguntas?