domingo, 19 de octubre de 2014

AsyncTask

Para las operaciones complejas dentro de una app es habitual el empleo de multiproceso, de forma que la aplicación no quede bloqueada mientras se efectúan dichas tareas.
En Android existen diversas formas para implementarlo, por ejemplo se pueden emplear Threads Java, pero tiene una serie de implicaciones con el acceso a componentes del interfaz gráfico que dificulta su gestión.
En Android se pueden emplear las AsyncTask, que representan una forma sencilla de crear procesos independientes, aislando al programador del uso de Threads. Para poder emplear una tarea de esta forma es necesario definir una clase que herede de la clase AsyncTask y sobreescribir los métodos correspondientes.

Compatibilidad

v3

Lo mínimo necesario

El método principal es doInBackground, y es el único que hay que sobrescribir obligatoriamente. En el siguiente código se crea una clase privada dentro del Activity para utilizar la AsyncTask:
public class MainActivity extends Activity {
      
/**
        * Los parámetros de la clase indican
        * Object tipo del array de entrada
        * Integer tipo para incremento de progreso (no se usa en este caso)
        * String tipo devuelto por doInBackground (no se usa en este caso)
 */
private class Tarea extends AsyncTask<Object, Integer, String>{
            
@Override
protected String doInBackground(Object... arg0) {
                    try {
                           Thread.sleep(1000);
                    } catch (InterruptedException e) {
                           ;
                    }
                    return "Finalizado";
             }

       }

...

Para ejecutar la tarea simplemente se crea una instancia de esta clase y se invoca al método execute. El parámetro del método execute es el array de Object que en este caso recibe el método doInBackground (es posible no pasar ningún parámetro).
Tarea tarea = new Tarea();
tarea.execute();

Como se ha comentado, el método doInBackground se encarga de ejecutar un proceso independiente. Es necesario tener precaución ya que este método no podrá acceder a los componentes del interfaz gráfico, pero AsyncTask posee otros métodos para solucionar este aspecto, onPreExecute se ejecuta antes de doInBackground y puede emplearse para inicializar elementos del interfaz, mientras que onPostExecute se ejecutará al finalizar la tarea y recibe el resultado producido en doInBackground.
/**
 * Los parámetros de la clase indican
 * Object tipo del array de entrada
 * Integer tipo para incremento de progreso (no se usa en este caso)
 * String tipo devuelto por doInBackground y recibido por onPostExecute
 */
private class Tarea extends AsyncTask<Object, Integer, String>{

       @Override
       protected void onPreExecute(){
             TextView tv = (TextView) findViewById(R.id.tvText);
             tv.setText("Iniciado");
       }
            
       @Override
       protected String doInBackground(Object... arg0) {
             try {
                    Thread.sleep(1000);
             } catch (InterruptedException e) {
                    ;
             }
             return "Finalizado";
       }
            
       @Override
       protected void onPostExecute(String result){
             TextView tv = (TextView) findViewById(R.id.tvText);
             tv.setText(result);
       }

}

ProgressDialog

Las AsyncTask además facilitan la gestión de diálogos de progreso asociados al proceso en ejecución. El método onProgressUpdate se encargaría de la actualización del progreso de un diálogo de progreso definido.
Cuando la tarea no tiene una duración determinada se emplea un diálogo infinito muy habitual en Android, y se mostrará y ocultará gestionándolo desde los métodos correspondientes del AsyncTask:
private class Tarea extends AsyncTask<Object, Integer, String>{

private ProgressDialog dialog;

       @Override
       protected void onPreExecute(){
dialog = ProgressDialog.show(getActivity(),
getString(R.string.app_name), getString(R.string.buscando), true);

             ...
       }
            
       @Override
       protected String doInBackground(Object... arg0) {
             ...
       }
            
       @Override
       protected void onPostExecute(String result){
dialog.dismiss();

             ...
       }

}

Cancelar diálogos

El método onCancelled de un AsyncTask se ejecuta automáticamente cuando la tarea se interrumpe a través del método cancel, y se encargará de cancelar los procesamientos que se encontraran en curso y dejar a la app en un estado estable. El método cancel puede ser invocado al pulsar un elemento del interfaz o al pulsar el botón atrás, quedando la tarea interrumpida.
En el siguiente código se aprovecha el método onCancel del diálogo de progreso (lanzado al pulsar back) para detener la tarea:
@Override
protected void onPreExecute() {
dialog = ProgressDialog.show(getActivity(),
getString(R.string.app_name), getString(R.string.buscando), true);
       dialog.setCancelable(true);
       dialog.setOnCancelListener(new OnCancelListener() {
              @Override
               public void onCancel(DialogInterface dialog) {
                   TareaEnvio.this.cancel(true);
               }
});
}

@Override
protected void onCancelled() {
       TextView tv = (TextView) findViewById(R.id.tvText);
       tv.setText("Cancelado");
}

Referencias

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

No hay comentarios:

Publicar un comentario