viernes, 30 de agosto de 2013

Tutorial: Android tareas en segundo plano con AsynkTask y barra de progreso

Buenos días!
Hoy vamos a ver un tutorial muy interesante a la vez que practico para cualquier tipo de aplicación y más si requiere Internet o cálculos que pueden llevar un tiempo.
Una tarea en segundo plano es aquella tarea que se a desprendido de la original para no bloquear esta mientras hace un proceso que puede llevar desde unos segundo a minutos enteros. En este tutorial explicaremos como funciona un Asynctask y pondremos el ejemplo con una barra de progreso que se verá en la aplicación original pero que el calculo de ésta esta en segundo plano, de esta manera la original no se bloquea y  podemos seguir viendo movimiento, por ejemplo un ProgressBar. Espero que haya quedado más o menos claro.
Vamos a pasar a ver el código como siempre totalmente explicado:

//Creamos la clase AsyncTask como vemos contiene 3 parámetros
//en este caso <Void, Integer, Boolean> en cada caso según lo que
//queramos suelen cambiar, para que es cada uno de ellos?
//1º (ej.string) es el parámetro que enviamos al Asyn y es recogido por doInBackGround
//2º (ej.Inetger) es el parámetro que recibira onProgressUpdate
//3º (ej.Boolean) el el parámetro que para del doInBackGround a onPostExecute
//Todos pueden cambiar según nuestro objetivo pero el orden siempre va a ser así
private class Descargar extends AsyncTask<String, Integer, Boolean> {
 @Override
        protected void onPreExecute() {
     //En este ejemplo el onPreExecute no lo utilizaremos
     //Se utiliza en casos que por ejemplo queremos inicializar
     //algunos valores que se utilizarán en este AsyncTask
 }
          
 @Override
        protected Boolean doInBackground(String... params) {
  //Recibimos por ejempo un link de descargar
  String link = params[0];
  //Aquí es dónde ira todo el proceso en segundo plano
  //es decir taréas que normalmente tardan unos segundos o 
  //minutos y si no fueran en segundo plano el terminal se 
  //bloquearía sobre ese tiempo
  for(int a=0; a<=100; a++) {
   //En este ejemplo pondremos un simple sleep 
   //para hacer ver que la taréa tarda
          try {
       Thread.sleep(250);
   } catch (InterruptedException e) {
       e.printStackTrace();
   }
          //Vamos actualizando el onProgressUpdate a medida
          //que hay cambios en el doInBackGround
          publishProgress(a);
  }
            return true;
           }

        @Override
        protected void onProgressUpdate(Integer... values) {
             super.onProgressUpdate(values);
             //vamos añadiendo los valores que recibimos a la barra
             //de progreso
             barra_cargando.setProgress(values[0]); 
        }
           
        @Override
        protected void onPostExecute(Boolean result) {
            //Si al acabar el background recibimos un True
            //mostraremos mensaje de proceso finalizado :D
            if(result){
               Toast.makeText(MainActivity.this, "Listo!"
               ,Toast.LENGTH_LONG).show();
            }
        }
   } 
Para ejecutar todo ese Asynctask bastaría con un botón:
//Al clicar el botón
bt_descargar.setOnClickListener(new OnClickListener() {
 @Override
 public void onClick(View v) {
  //Ejecutamos el synctask y en este caso le pasamos un link de descarga
  new Descargar().execute("http://google.com/image.jpg");
 }
});

Como siempre podéis descargar el proyecto entero en eclipse en el siguiente link: 




Muchas gracias a todos!! Espero vuestras dudas y comentarios!!  +1

3 comentarios:

  1. Buenas Victor Maldonado, interesante el tutorial. Tengo una duda como hago desde una clase aparte que extiende AsyncTask que no esta adentro de una clase que extiende activity, manipular los controles de una clase que extiende activity sin usar una referencia de esa clase, me dijeron que se puede hacer con una función callback, con la idea de que se devuelva a la clase que extiende activity, no se si es posible usar intent o algún otro mecanismo. Aqui te dejo el proyecto que hice en eclipse https://mega.co.nz/#!xkRA2SwQ!GXZGcnBaw5vPg4sRR5qFRz_8VXNWMdJ0wDCT7klzBv8 si quieres echarle una revisada me da error en el debug y al ejecutarla.......

    ResponderEliminar
    Respuestas
    1. Buenas aJ, he mirado tu proyecto y la verdad es que repararé el funcionamiento del callback más adelante. Pero según veo llamas a new backgr().execute(); más de una vez una en el onCreate y otra en el onPostExecute nose si eso estaría bien, y después estado mirando y no veo muy bien la conexión del Callback.class con el MainActivity.
      Lo siento por no poder ayudarte repasaré este tema. Si no veo oportuno crearé un tutorial.

      Muchas gracias por tu comentario y por visitarnos y siento no poder ayudar más.

      Eliminar
    2. Ok, Victor maldonado gracias por responderme.

      Coloque el backgr().execute(); en onCreate para que iniciara un proceso en segundo plano con el objetivo de cambiar el texto del textview, reflejando un conteo de 0 a 9 infinito.

      Relacionado con el onPostExecute coloque que se iniciara de nuevo el asynctask por si se produce alguna excepción en el try catch con la idea de que siga contando y no se pare.

      Logre cambiar el texto del texview pasando una referencia de la clase mainactivity (no estoy seguro si estoy pasando una referencia...) como parámetro en el constructor de la clase backgr. Aquí te dejo el proyecto que hice relacionado a esto -> https://mega.co.nz/#!sw5m1BQC!d19ivHJKeAvz-1SIx6ajfhq9AZkg3RRfnY-V2K7EzT8


      Eliminar