Vamos a programar #58 - AsyncTask en java.

Hola de nuevo a todos, el día de hoy vamos a ver cómo usar la clase "AsyncTask" para proveer de un poco de multi-threading a una aplicación.



En el la aplicacion de los números de Muchhausen, vimos que empleamos una subclase llamada "UpdateList" que hereda de "AsyncTask", el nombre de la clase es bastante descriptivo, puesto que lo que hace es ejecutar una tarea de forma asíncrona.

la clase AsyncTask posee los siguientes metodos:

  • doInBackground(Params... params).
    • Este método se debe de sobrecargar para poder realizar una tarea de forma asíncrona.
  • onCancelled(Result result)
    • Se ejecuta en el hilo principal despúes de que cancel(boolean) es invocado o  doInBackground(Object[]) ha terminado.
  • onPostExecute(Result result).
    • Se ejecuta cuando doInBackground(Params...) ha terminado su ejecución.
  • OnPreExecute()
    • Se ejecuta en el hilo principal antes que doInBackground(Params...).
  • onProgressUpdate(Progress... values)
    • Este método se ejecuta despúes de que publishProgress(Progress...) is invoked.
  • publishProgress(Progress... values)
    • Este método puede ser invocado  desde doInBackground(Params...) para actualizar elementos en el hilo principal.

Para tener una idea de cómo funciona, retomemos el ejemplo de los números de Munchhausen. Para empezar, ¿qué es lo queremos hacer?, en este caso buscamos crear una lista de resultados en la que indiquemos si un número n cumple o no la conjetura. entonces para construir la clase AsyncTask de acuerdo a nuestros requerimientos, puede ser de la siguiente forma: private  class UpdateList extends AsyncTask<Integer,Void,ArrayList> y cada parametro corresponde a:

  • Integer, son los parametros que se usaran en doInBackground(), son del tipo integer porque son los números que vamos a usar cómo limites inferior y superior, y un tercero que se usará para indicar  si se deben mostrar o no todos los números.
  • Void, el segundo parametro cómo en eeste caso no mostramos ningún progreso en concreto, simplemente mostramos el dialogo de forma indeterminada, usualmente suele ser un valor Integer.
  • ArrayList,  debido a que todos los resultados de los calculos los guardamos en un "ArrayList", para poder usar esa lista cómo resultado de la ejecución, debemos de hacerlo del mismo tipo, si por alguna razón nuestro proceso debe de devolver un valor "boolean", "String" o etc. el tercer parametro debe de ser de ese tipo.
Para ejecutar el proceso, en el hilo principal debemos de llamar a "new UpdateList().execute(Min,Max,ShowAll);" los parámetros que usemos aqui se convertiran en un array y se asignaran a la variable que se use cuando definimos nuestro proceso.

Ahora veamos el siguiente código:

// Original de https://developer.android.com/reference/android/os/AsyncTask
 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
	 protected Long doInBackground(URL... urls) {
		 int count = urls.length;
		 long totalSize = 0;
		 for (int i = 0; i < count; i++) {
			 totalSize += Downloader.downloadFile(urls[i]);
			 publishProgress((int) ((i / (float) count) * 100));
			 // Escape early if cancel() is called
			 if (isCancelled()) break;
		 }
		 return totalSize;
	 }

	 protected void onProgressUpdate(Integer... progress) {
		 setProgressPercent(progress[0]);
	 }

	 protected void onPostExecute(Long result) {
		 showDialog("Downloaded " + result + " bytes");
	 }
 }
 

Esta clase se construye de la siguiente forma: DownloadFilesTask extends AsyncTask<URL, Integer, Long>,  suponiendo que se llame a ejecutar con los siguientes parametros: "URL1", "URL2","URL3","URL4"..."URL10". El parámetro URL contendrá estos diez valores distintos entonces en "doInBackground(URL.. urls)" lo que se hace es primero asignar los parámetros a la variable "urls" y luego medir los elementos con "urls.length" y cada parámetro pasado al momento de iniciar la ejecución, estará en esta matriz. EL resultado de "doInBackground"  es del tipo "Long" que usaremos en "onPostExecute" para mostrar al usuario cuantos bytes se descargaron. Cada vez que se ejecute "publishProgress()" en "doInBackGround()", se ejecutará "onProgressUpdate()", en esta parte es donde debemos de cambiar cualquier indicador de progreso. finalmente en "onPostExecute()", mostraremos un dialogo con la información de cuantos bytes se descargaron.

En post anteriores ya hemos usado "AsyncTask"

Y bien, por ahora es todo, en el siguiente post añadiremos una barra de progreso y entenderemos mejor cómo y cuando debemos de hacer uso de "AsyncTask".

Los leo luego.

No hay comentarios.