Читать книгу El gran libro de programación avanzada con Android - José Enrique Amaro Soriano - Страница 20

Оглавление

4. PROCESOS EN BACKGROUND

En Android podemos ejecutar simultáneamente partes de un programa como procesos paralelos. Cada uno de estos procesos se denomina thread, o hilo, y se ejecuta en background con una prioridad determinada bajo el control de un objeto de la clase Thread de Java. Una forma de crear un hilo es definir una clase que extienda a la clase Thread. La nueva clase debe sobrescribir el método run(), que se ejecutará cuando se inicie el hilo. Otra forma de crear un hilo es implementando la interfaz Runnable. En este capítulo veremos algunos ejemplos del uso de hilos (en el libro Android se pueden ver ejemplos alternativos).

Inicialmente, solo hay un hilo asociado a una actividad, el hilo principal, que consiste en una serie de instrucciones o sentencias que se ejecutan secuencialmente. Además, este hilo es el que controla los elementos de la interfaz de usuario (UI) que se muestran en pantalla. En este capítulo veremos también cómo se puede modificar la UI desde otro hilo.

4.1. Uso de Timer y RunOnUiThread

La clase Timer del paquete java.util permite programar tareas que se ejecutan transcurrido un tiempo, de forma única o secuencialmente. Un temporizador es un objeto de tipo Timer. Para programarlo se utilizan los métodos schedule, para realizar una única tarea, o scheduleAtFixedRate, para una serie repetitiva de tareas. Para detener el temporizador, se usa el método cancel. Por ejemplo, para programar una tarea repetitiva, escribiríamos lo siguiente:


Aquí, retraso es el tiempo de espera hasta que se ejecute la acción; periodo, el tiempo de repetición y timerTask es un objeto de una subclase de TimerTask, que contiene las instrucciones a ejecutar a través de su método run.


El método run de TimerTask se ejecuta en background en su propio hilo. Por lo tanto, no podremos modificar la UI (la pantalla), pues los objetos de esta, por ejemplo un TextView, solo se pueden cambiar desde el hilo principal. Para sincronizar con la UI y modificar sus objetos, podemos usar el método runOnUiThread(Runnable), de la clase Activity. Su argumento es un objeto de tipo Runnable cuyo método run se ejecutará en sincronía con el hilo principal y permitirá modificar los objetos View que en él residan.

La siguiente actividad ilustra el uso de Timer combinado con RunOnUiThread para mostrar un cronómetro que avanza cada 100 milisegundos. Usaremos el siguiente layout:


La actividad Temporizador.java se detalla a continuación. Contiene dos clases internas: Tarea, subclase de TimerTask, y CambiaTexto, que implementa a la interfaz Runnable, para modificar el TextView. No es necesario usar invalidate para redibujar la pantalla. En la figura 4.1. se muestra el resultado.


Figura 4.1. Cronómetro con Timer y RunOnUiThread.



4.2. Modificación de la UI con post

Alternativamente al método runOnUiThread de la clase Activity, podemos usar el método post(Runnable) de la clase View. El argumento de post debe definir un método run que se ejecutará en el mismo hilo que la UI. Veamos un ejemplo en el que modificamos ligeramente el programa anterior, sustituyendo runOnUiThread por tv.post. También se ha modificado el texto a escribir. No es necesario usar invalidate para actualizar el TextView. En la figura 4.2. se muestra el resultado.


Figura 4.2. Modificación de la UI con View.post.



4.3. Modificación de la UI con Handler.post

Una tercera forma de modificar la interfaz de usuario consiste en usar un controlador, u objeto de la clase Handler. A este objeto le pasaremos un objeto Runnable mediante el método Handler.post(), que lo añade al hilo principal. En el siguiente ejemplo, que es una variación de los dos anteriores, se explica el modo de hacerlo. El resultado se muestra en la figura 4.3. (ver Android para otros ejemplos del uso de la clase Handler pasándole un mensaje).




Figura 4.3. Modificación de la UI con Handler.

4.4. Métodos combinados para modificar la UI

Los tres métodos anteriores, usando RunOnUiThread(), View.post() y Handler.post(), pueden combinarse como en el siguiente ejemplo, donde abrimos tres hilos, cada uno de los cuales varía el color de un texto de forma aleatoria. Para ello modificamos la clase CambiaTexto de los ejemplos anteriores añadiéndole dos parámetros: el texto a modificar y un número que se utiliza para cambiar las componentes RGB del color mediante un algoritmo. En la figura 4.4. se muestra el resultado.

El layout, definido en el siguiente fichero main.xml, contiene tres TextView.



A continuación se detalla el fichero Java de la actividad CambiaColor.






Figura 4.4. Tres hilos simultáneos cambiando el color de un texto.

4.5. Modificación de la UI con AsyncTask

La clase AsyncTask permite realizar tareas en background y publicar los resultados en la interfaz de usuario sin necesidad de crear hilos y sincronizarlos con la UI. Para utilizarla hay que definir una subclase, que toma tres parámetros genéricos (ver Apéndice B, secciones B.3 y B.4 sobre el uso de genéricos en Java).


Aquí, X, Y, Z son tres nombres de clases utilizados para los datos del input, progreso y resultado, respectivamente. La clase anterior debe sobrescribir necesariamente el método doInBackground, que admite un número variable de parámetros de tipo X y devuelve un dato de tipo Z (ver Apéndice B, en el que se discuten los métodos de Java con un número variable de parámetros).


El método doInBackground se ejecuta en un nuevo hilo. Desde este hilo se pueden publicar actualizaciones en el hilo principal llamando al método publishProgress(Y … progreso). Entonces, el hilo principal se encarga de invocar el método onProgressUpdate(Y … progreso). Al finalizar la ejecución del proceso en background, el hilo principal invoca el método onPostExecute(Z resultado).

En el siguiente ejemplo se ilustra el uso de AsyncTask, donde un contador se incrementa desde 0 hasta 99 y en cada paso mostramos su valor en un objeto TextView en la pantalla, aumentando proporcionalmente su tamaño. Al final de la ejecución se añade el texto «Fin», como se muestra en la figura 4.5.




Figura 4.5. Uso de AsyncTask para ejecutar un proceso en background y publicar su progreso en el hilo principal.

4.6. Máquina tragaperras

El siguiente ejemplo es una aplicación práctica de AsyncTask para ejecutar varios hilos simultáneamente. Se trata de un juego que simula una máquina tragaperras. La actividad slotMachine consiste en tres columnas de imágenes que van permutando simulando la rotación de imágenes en cada uno de los tres rodillos de una máquina tragaperras. Cada columna se pone en marcha o se para independientemente por medio un botón que, al ser pulsado, cambia el valor de la variable de control continuar[columna]. Si esta es true, ejecuta un nuevo proceso AsyncTask para mostrar las imágenes en movimiento. Si es false, el proceso AsyncTask se detiene automáticamente. La clase AsyncTask definida más abajo requiere como parámetro de entrada el número de columna. Cada vez que se ejecuta onPostExecute, se determina si los tres procesos se han detenido, en cuyo caso comprueba si las imágenes de la segunda fila coinciden. En caso afirmativo, se escribe el mensaje «¡¡¡PREMIO!!!» en la pantalla.

Además, se han añadido tres botones que permiten controlar la velocidad del movimiento de las imágenes, incrementando o disminuyendo el valor de la variable dificultad, que no es más que el tiempo, en microsegundos, que cada imagen se muestra en pantalla.

El layout de esta aplicación consiste en una tabla con tres columnas. Previamente se han copiado las nueve imágenes jpg (de tragaperras1.jpg a tragaperras9.jpg) en el directorio de recursos res/drawable-hdpi de nuestra aplicación. Las imágenes son cuadradas con 250 píxeles de lado.

El fichero main. xml es el siguiente:





A continuación se detalla el fichero TragaPerras.java. La secuencia de las nueve imágenes, que se ha almacenado en la matriz secuencia[3][9], es diferente en cada columna. En la figura 4.6. se muestran las capturas de pantalla de la máquina tragaperras en funcionamiento.






Figura 4.6. Juego de la máquina tragaperras usando AsyncTask.

El gran libro de programación avanzada con Android

Подняться наверх