Inicio > Android, Java, Programación > Creando tareas asíncronas en Android con AsyncTask

Creando tareas asíncronas en Android con AsyncTask


En determinadas ocasiones, tenemos programas que tardan bastante rato en realizar una tarea en concreto y queremos que esta no bloquee la aplicación mientras se está ejecutando.

Para solventar esto normalmente se hace uso de los Threads (hilos). Para ello, creamos un hilo adicional para nuestra tarea y continuamos con el hilo normal para el resto de la aplicación.

El problema es que la interfaz gráfica (UI) de Android no permite llamadas desde otros hilos que no sea el suyo, así que si necesitamos realizar alguna actualización (aumentar barra de porcentaje, añadir información…) nuestra aplicación se cerrará.

Hay distintos métodos para poder acceder al hilo de la UI y actualizarla desde este (Handler, runOnUiThread..), pero yo explicaré el que me ha parecido más limpio, seguro y fácil, las AsyncTasks.

Extendiendo de AsyncTask (tarea asíncrona) podemos crear una clase que tenga entre 1 y 4 métodos según necesitemos.

Además, la clase AsyncTask dispone de tres tipos de parámetros distintos, que tendremos que especificar cuando declaremos nuestra clase. Veamos un ejemplo:

public class MiTarea extends AsyncTask<Params, Progress, Result> {
}

Los tres parámetros son los siguientes:

  • Params:  Datos que pasaremos al comenzar la tarea
  • Progress: Parámetros que necesitaremos para actualizar la UI.
  • Result: Dato que devolveremos una vez terminada la tarea.

Veámoslo con un ejemplo:

Quiero crear una aplicación que descargue un archivo de internet. A la tarea le pasaré la dirección del fichero (String), conforme vaya descargándolo irá mostrando el porcentaje que que lleva (Float) y una vez terminado devolverá el número de bytes del fichero (Integer). Nuestra instancia quedaría así:

public class MiTarea extends AsyncTask<String, Float, Integer> {
}

Si alguno de los parámetros no lo necesitamos, podremos substituirlo por Void.

Los métodos que tendremos que escribir de nuestra clase son los siguientes, aunque solo es obligatorio el primero:

protected Result doInBackground(Params... p) {
}

Este método será el encargado de realizar la tarea en segundo plano. Como vemos, recibe un número cualquiera de parámetros del tipo Params, así que debemos tratar a p como un array.

Este método se ejecuta en otro hilo, por lo que no podremos modificar la UI desde él. Para ello, usaremos los tres métodos siguientes.

protected void onPreExecute() {
}

Este método se ejecutará antes de doInBackground, por lo que podremos modificar la interfaz para indicar el comienzo de la tarea (colocar un  cargando, desactivar botones…).

protected void onProgressUpdate (Progress... values){
}

Este método permitirá actualizar la interfaz mientras se ejecuta la tarea asíncrona. Para ello, desde doInBackground deberemos llamar a publishProgress y pasarle los parámetros oportunos.

protected void onPostExecute (Result result){
}

Este último método, como habréis supuesto, se ejecuta tras terminar doInBackground y recibe como parámetro lo que este devuelva.

Quizás ahora no lo tenéis del todo claro, pero veamos el ejemplo anterior ya implementado.

public class MiActividad extends Activity {
    private ProgressDialog dialog;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        dialog = new ProgressDialog(this);
        dialog.setMessage("Descargando...");
        dialog.setTitle("Progreso");
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        dialog.setCancelable(false);
        //Realizamos cualquier otra operación necesaria
        //Creamos una nueva instancia y llamamos al método ejecutar
        //pasándole el string.
        new MiTarea().execute("http://www.ejemplo.com/file.zip");

      }

     private class MiTarea extends AsyncTask<String, Float, Integer>{

    	 protected void onPreExecute() {
    		 dialog.setProgress(0);
    		 dialog.setMax(100);
                 dialog.show(); //Mostramos el diálogo antes de comenzar
          }

          protected Integer doInBackground(String... urls) {
        	 /**
        	  * Simularemos que descargamos un fichero
        	  * mediante un sleep
        	  */

              for (int i = 0; i < 250; i++) {
                    //Simulamos cierto retraso
            	    try {Thread.sleep(200); }
                    catch (InterruptedException e) {}

                    publishProgress(i/250f); //Actualizamos los valores
                }

              return 250;
          }

          protected void onProgressUpdate (Float... valores) {
        	  int p = Math.round(100*valores[0]);
        	  dialog.setProgress(p);
          }

          protected void onPostExecute(Integer bytes) {
        	  dialog.dismiss();
          }
    }
}

Categorías: Android, Java, Programación Etiquetas: , ,
  1. 21 febrero, 2011 a las 1:08 am

    Me ha servido de mucho. Lo usé para mi primera aplicación:

    Muchísimas gracias por el post… 😉

  2. android nuevo
    14 abril, 2011 a las 3:26 am

    así de simple es como se debe explicar en un blog, muy buen post!!

  3. foreverjos
    15 abril, 2011 a las 4:58 pm

    Excelente me funciono, nada mas que tengo un problema, tu manejas un AsyncTask con un ProgressDialog y yo utilizo un Thread IGUAL CON UN ProgressDialog, mi problema es que yo lo utilizo como una segunda venta, es decir cuando el usuario entra a mi aplicación primero abre un splash y luego aparece la ventana con el ProgressDialog;

    Uno de mis problemas es que si el proceso dura demasiado tiempo el teléfono se bloquea y al desbloquearlo, me carga otra vez el ProgressDialog desde el principio.

    Otro Problema es si el usuario presiona la tecla HOME, esta sale de la aplicacion, y al momento de entrar de nuevo en la aplicación, me carga el splash y de nuevo el ProgressDialog, en lugar de mostrar el avance que ya tenia recorrido, lo curioso es que cuando termina el proceso, tengo ya 2 actividades abiertas, en lugar de 1 sola, a que crees que se deba..

  4. foreverjos
    15 abril, 2011 a las 5:00 pm

    por cierto ya lo probé de las 2 formas y las 2 se comportan igual

    • 15 abril, 2011 a las 5:04 pm

      El Thread el problema que tiene a que puede ocasionar bloqueos del Activity si modificas algunas partes del interfaz, lo cual el AsyncTask controla mejor. De hecho, el AsyncTask es un Thread controlado.

      En cuanto a tu otro problema, debe a que el Activity se resetea por defecto, tendrías que modificar esto de forma manual. Es bastante tedioso, pero Googleando podrás encontrar algo, yo es que no lo he necesitado todavía así que no te puedo ayudar mucho al respecto.

  5. pablo
    30 junio, 2011 a las 11:03 am

    Muy bien explicado. Gracias

  6. Diego Gallego
    6 septiembre, 2011 a las 9:30 am

    Hola, mi aplicacion permite manejar la orientacion landscape y portrait. El problema se da cuando en medio de la descarga giro la pantalla ya que se reinicia todo el activity. Me podrias ayudar con esto?

    • 6 septiembre, 2011 a las 9:48 am

      Tienes que controlar manualmente el cambio de orientación. Lo que debes hacer es sobreescribir el método
      public void onConfigurationChanged(Configuration newConfig)
      Y agregar android:configChanges="orientation|keyboardHidden" en la especificación del activity en el Manifest.

      El método podría quedar algo así:
      public void onConfigurationChanged(Configuration newConfig) {
      setContentView(R.layout.milayout);
      boton = findViewById(R.id.boton);
      ....
      }

      Esto hará que coja el nuevo layout pero sin reiniciar todo. Como ves, tendrás que volver a obtener los Views de nuevo, pues al cambiar el layout, estos cambian también.

      No tengo el Eclipse ahora, así que puede que haga algún error, pero más o menos sería algo así.

  7. Javier Pérez
    6 septiembre, 2011 a las 3:24 pm
  8. Juanma
    20 noviembre, 2011 a las 4:46 pm

    Me ha parecido genial. Funciona a las 1000 maravillas y es fácil de entender. Muchas gracias

  9. 5 diciembre, 2011 a las 11:21 pm

    Muy buen post, me sirvió mucho.
    Muchas gracias.

  10. 3 enero, 2012 a las 8:13 pm

    Muy claro ha quedado. Lo probaré. Muchas gracias.

  11. AlexHB
    31 enero, 2012 a las 10:13 pm

    como se usa la variable enviada aqui ‘MiTarea().execute(«http://www.ejemplo.com/file.zip»);’ en el bloque protected Integer doInBackground(String… urls) {….} no lo veo, por lo demas perfecto. muchas gracias.

    • 31 enero, 2012 a las 10:18 pm

      String… urls es un parámetro de «infinidad de parámetros» y has de tratarlo como si se tratase de un array.
      En nuestro caso, como pasamos solo un parámetro, para acceder a él solo debemos usar urls[0] y ahí tenemos nuestra variable.
      Si pasásemos dos datos como en MiTarea().execute(«url 1», «url 2»); pues tendríamos que acceder a las URLs mediante urls[0] y urls[1].

      • AlexHB
        31 enero, 2012 a las 10:48 pm

        muchas gracias no me habia fijado en eso.

  12. Jose Mª
    14 febrero, 2012 a las 9:54 am

    Hola, enhorabuena por el artículo funciona perfectamente y es realmente el método mas claro. Solo tengo una duda que he intentado probar en un proyecto mío y no me funciona.
    Digamos que en background pongo en marcha una aplicación de mucho peso, y pretendo que mientras tanto en el onProgressUpdate(); se vaya modificando el mensaje que aparece en el ProgressDialog. Lo que ha de poner en cada mensaje lo saca de un fichero de registro.
    El problema:
    Mi problema es que no se me lanza el onProgressUpdate(); solo se me lanza si lo llamo (a lo mejor esta parte no me ha quedado tan clara). El problema es que solo lo puedo llamar dentro del cuerpo de la AsyncTask.
    Muchas gracias.

    • 14 febrero, 2012 a las 10:04 am

      El onProgressUpdate no se lanza automáticamente, debes hacerlo tú llamando al publishUpdate.
      Por ejemplo, si estás obteniendo los mensajes podrías ser así.

      protected Void doBackground(Void… a) {
      while ( hayMensajes() )
      publishUpdate(obtenerMensaje() );

      }

      protected void onProgressUpdate(String… m){
      dialogo.setMessage(m[0);
      }

  13. Jose Mª
    14 febrero, 2012 a las 10:09 am

    Muchas gracias

  14. fitopato
    11 May, 2012 a las 2:21 pm

    Enhorabuena por el artículo, funciona de maravilla y muy bien explicado. Así da gusto.

  15. 13 julio, 2012 a las 12:53 am

    en la actividad yo llamo al
    new AsyncTask(…);
    si luego de esto quiero continuar con otra cosa p.e.
    Activity
    {
    new AsyncTask(…);
    if(algo que cambio con la AsyncTask) . . .
    }
    nunca llega a entrar al if porque el hilo normal ya ejecuto ( if ) esto y el hilo asincrono aun no termino como podria hacer para que primero acabe la tarea del hilo asincrono y siga despues con el if con todos los cambios hechos con ASyncTask help plz

    • 13 julio, 2012 a las 1:12 am

      Lo suyo sería que colocases todo lo que quieres que se ejecute tras el asíncrono en un método aparte y en el postExecute del asynctask llames a dicho método.

      • Sebas
        25 julio, 2012 a las 12:13 pm

        Muy bueno el post y múy útil, el problema que tengo es que desde el postExcute no puedo acceder a nada del activity que llamó al asynctask, cómo debería de hacerlo? o llamar un nuevo intent, pero tampoco me deja

      • 25 julio, 2012 a las 12:23 pm

        Donde has creado el AsyncTask? Yo suelo crearlo dentro del propio activity y así acceder a los datos.

      • Sebas
        25 julio, 2012 a las 12:26 pm

        Dentro del Main Activity hago la llamada al AsyncTask, pero dentro de éste último, no me deja acceder a los objeto de la actividad que lo llama o no sé cómo hacerlo.

        Gracias

      • 25 julio, 2012 a las 12:28 pm

        Ahí es donde instanacias el objeto, pero donde declaras el clase?

        Si te fijas en el ejemplo, hago la clase dentro de la clase, como una clase privada.

        Si la creas en un .java aparte, tendrías que pasarle por el contructor o algún método el activity. Pero vamos, yo veo más simple que hagas un private class y arreando.

      • Sebas
        25 julio, 2012 a las 12:59 pm

        Muchas gracias por la pronta respuesta. Al final hice una clase aparte con un nuevo constructor en cual le paso la activity. En el postExecute llamo a un metodo del activity y puedo acceder a lo que necesito.

        Saludos

  16. Juan Chorizo
    30 noviembre, 2012 a las 4:02 pm

    MUCHAS GRACIAS!
    Perfectamente explicado y funciona muy bien!
    Había estado buscando algo como ésto por días.

  17. Diego Franco
    25 diciembre, 2012 a las 2:20 am

    yo tengo un problema con los threads y los hilos, y quisiera ver la posibilidad de que me pudieras ayudar, lo mio no es un progressdialog sino que quiero realizar una tarea con hilos, en mi caso es deletrear una palabra con imagenes:

    public void onClick(View v) {

    new Handler().postDelayed(new Runnable(){
    public void run(){
    letra(0);
    }
    }, 1000);

    }
    });

    }//fin bundle

    private void letra(int i) {

    String t = etxt.getText().toString();
    String lower = t.toLowerCase();

    char[] array = lower.toCharArray();

    for(int j=0; j<array.length;j++){

    if(array[j] == 'a' || array[j] == 'A'){

    img = (ImageView)findViewById(R.id.img);
    img.setImageResource(R.drawable.aa);
    img2 = (ImageView)findViewById(R.id.img2);
    img2.setImageResource(R.drawable.image_1);

    }

    if(array[j] == 'b' || array[j] == 'B'){

    img = (ImageView)findViewById(R.id.img);
    img.setImageResource(R.drawable.bb);
    img2 = (ImageView)findViewById(R.id.img2);
    img2.setImageResource(R.drawable.image_2);
    }

    el problema es que solo me manda la ultima letra del EditText y quiero que vaya recorriendo la palabra letra por letra, gracias!

  18. Mauma
    15 marzo, 2013 a las 10:38 pm

    Excelente!! muchas gracias

  19. Ivan
    14 May, 2013 a las 5:22 am

    Estimado muy buen post, pero tengo una duda. La Asynctask solo se debe ejecutar desde la actividad principal o ¿la puedo usar dentro de una clase aparte para llamarla desde la actividad principal o de otra actividad?

    • 14 May, 2013 a las 8:08 am

      Puedes ejecutarla desde donde quieras

      • Ivan
        15 May, 2013 a las 5:13 am

        ¿Y como lo hago para escribir en un textview en la actividad principal?

  20. Karlos
    19 septiembre, 2013 a las 12:50 pm

    Perfecto. Es justo lo que buscaba.

  21. Christiam Niño
    25 septiembre, 2013 a las 8:01 pm

    Cordial Saludo, porque mi aplicacion tengo que presionarla 2 veces para que acceda al codigo de la tarea asincrona, a que se debe eso gracias

    • 25 septiembre, 2013 a las 8:12 pm

      Pues sin ver el código no tengo ni idea. Puede haber miles de motivios

  22. Christiam Niño
    25 septiembre, 2013 a las 8:19 pm

    Codigo de Activity

    public class LoginActivity extends Activity {
    private EditText etLogin = null;
    private EditText etPassword = null;
    private Button btIngresa;
    private Button btSalir;
    private String strLogin=»»;
    private String strPassword=»»;
    //Variable que guarda el valor del servicio web en la tarea
    public String men=»-1″;

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);
    //Variable que almacena el objeto de la actividad Login
    final LoginActivity _act = this;

    //para manejar los EditText
    etLogin = (EditText)findViewById(R.id.etUsuario);
    etPassword = (EditText)findViewById(R.id.etContrasena);

    //Reinicializar en vacio los cuadros de texto
    etLogin.setText(«»);
    etPassword.setText(«»);

    //Accion del boton Ingresar
    btIngresa = (Button)findViewById(R.id.btIngresar);
    btIngresa.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
    //Asignacion del valor de los cuadro de texto a las variables
    strLogin += etLogin.getText().toString();
    strPassword += etPassword.getText().toString();

    //Validación de ambos campos vacios
    if(strLogin==»» && strPassword==»»){
    Toast.makeText(getApplicationContext(), «Login y Password vacios»,
    Toast.LENGTH_SHORT).show();
    strLogin =»»;
    strPassword=»»;
    }

    //Validación del login vacio
    if((strLogin==»») && (strPassword !=»»)){
    Toast.makeText(getApplicationContext(), «Login vacio»,
    Toast.LENGTH_SHORT).show();
    strLogin =»»;
    strPassword=»»;
    }

    //Validación de password vacio
    if((strLogin!=»») && (strPassword ==»»)){
    Toast.makeText(getApplicationContext(), «Password vacio»,
    Toast.LENGTH_SHORT).show();
    strLogin =»»;
    strPassword=»»;
    }

    //Validación de login y password lleno
    if((strLogin!=»») && (strPassword !=»»)){
    //llamada a la tarea asincrona de servicio web
    ServicioAutenticar task = new ServicioAutenticar(_act);
    //Ejecución de la tarea asincrona
    task.execute(new String[] {strLogin,strPassword});
    //En la variable res se recoge el valor del servicio web
    String res = men.toString();
    //Verifica si el valor de la consulta en DB es positiva
    if(Integer.parseInt(res)==1){
    startActivity(new Intent(LoginActivity.this, PanelActivity.class));
    }else{
    strLogin =»»;
    strPassword=»»;
    Toast.makeText(getApplicationContext(), «Credenciales invalidas»,
    Toast.LENGTH_SHORT).show();
    }
    }
    }
    });
    }

    Codigo de Tarea

    public class ServicioAutenticar extends AsyncTask{
    private String namespace = «http://localhost/servicio/nusoap»;
    private String url = «http://localhost/servicio/nusoap/server.php»;
    private LoginActivity _loginActivity;
    private SoapObject request;
    private SoapSerializationEnvelope envelope;
    private HttpTransportSE transport;
    private String metodo = «autentica»;
    private String accion = «http://186.114.176.139/servicio/nusoap/server.php/autentica»;

    //Constructor del servicio autenticar
    public ServicioAutenticar(LoginActivity loginActivity){
    this._loginActivity = loginActivity;
    }

    //En la ejecución de la tarea asincrona
    @Override
    protected String doInBackground(String… params) {
    String res=»»;
    request = new SoapObject(namespace, metodo);
    request.addProperty(«login», params[0]);
    request.addProperty(«password», params[1]);
    envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.setOutputSoapObject(request);
    envelope.dotNet = true;
    transport = new HttpTransportSE(url);
    try {
    transport.call(accion, envelope);
    res = (String) envelope.getResponse().toString();
    } catch (Exception e) {
    Log.e(«ERROR», e.getMessage());
    }
    return _loginActivity.men = res;
    }

    //Despues de la ejecución de la tarea asincrona
    protected void onPostExecute(String result) {
    if(result!=»»){
    _loginActivity.men = result;
    }

    }

  23. Christiam Niño
    25 septiembre, 2013 a las 8:22 pm

    El problema es que lo ejecuto y cuando presiono el boton la primera vez no entra a la tarea asincrona creada y me toca presionarlo otra vez para que si entre, que pasara, o que estara mal

    • 25 septiembre, 2013 a las 8:37 pm

      No veo nada que pueda provocarlo. Usa el debugger en la zona del «onClick» a ver si es que salta en algún IF.

      Por cierto, en task.execute(new String[] {strLogin,strPassword}) no hace falta crear un array, al tener excute el parámatro «String…» puedes pasar todas las variables que quieras:

      task.execute(strLogin, strPassword)

  24. Allan Ortiz
    3 octubre, 2013 a las 2:27 am

    hola, tengo un problema, quiero manipular una variable q toma un valor en el onPostExecute pero cuando la tarea asincrona termina, la variable pierde su valor, y la variable esta declarada global, hay manera de sacar esa variable fuera de la tarea asincrona sin q pierda su valor o q en la misma tarea asincrona cuando termine de ejecutar no «destruya» esa variable o pierda su valor??

    • 3 octubre, 2013 a las 10:16 am

      No pongas la variable dentro del AsyncTask, ponla en la clase «padre».

  25. Allan Ortiz
    3 octubre, 2013 a las 5:22 pm

    /////////mira aqui tengo el codigo donde declaro las variables

    public class Notificaciones extends Activity {

    Bitmap loadedImage,imgbitmap;
    String imageHttpAddress,nctrl,nombre;
    private ImageView imageView;
    private TextView texto1,texto3;
    private String url = «http://192.168.16.2»;
    Intent llamar;
    JSONObject json;
    String imgstring,d,aa,bb,cc,dd,ee,ff,notimismensajess,notimismensajess2;

    //////supongo q esa es la clase padre, osea la clase de todo el activity que en este caso mi activity se llama «notificaciones», ahora te pongo la tarea asincrona

    class Cargartitulonoti extends AsyncTask {

    //String user,pass;
    protected void onPreExecute()

    {

    }

    protected String doInBackground(String… params) {
    //obtnemos usr y pass

    notimismensajes = consultamensajes3();
    //notimismensajess = notimismensajes[1].toString();

    // gggg = notimismensajes.length;

    //texto1.setText(String.valueOf( arrechar[2]));

    //consultamensajes(spinertemas.getSelectedItem().toString());
    return null;

    }

    /*Una vez terminado doInBackground segun lo que halla ocurrido
    pasamos a la sig. activity
    o mostramos error*/

    protected void onPostExecute(String result)
    {
    //llamar = new Intent(Notificaciones.this,Secundarioo.class);
    //llamar.putExtra(«arreglo», elementos);
    //llamar.putExtra(«estado», true);

    notimismensajess=(String.valueOf(notimismensajes[0]));

    if(notimismensajess!=notimismensajess2)
    {
    notimismensajess2=notimismensajess;
    texto3.setText(notimismensajess2);
    }

    new Cargartitulo().execute();

    }

    ///// lo que quiero es q la variable «notimismensajess2» no pierda el valor, aunque la tengo declarada globalmente pierde el valor

    • 3 octubre, 2013 a las 6:11 pm

      Lo que no veo es «donde» lo coge. Solo le pones el valor en

      if(notimismensajess!=notimismensajess2)
      {
      notimismensajess2=notimismensajess;
      texto3.setText(notimismensajess2);
      }

      Es decir, la primera vez que ejecutes ese código notimismensajess2 valdrá null y después debería mantener el valor de notimismensajess.

      ¿Es ese el problema? ¿Qué en las siguientes ejecuciones no mantiene el valor?

      Si sales del activity, normalmente, todos los valores «se reinician». ¿Podría ser ese el problema?

  26. Allan Ortiz
    3 octubre, 2013 a las 7:41 pm

    el valor lo coge de una funcion llamada «consultamensajes3();»

    notimismensajes = consultamensajes3();

    //////notimismensajes es una arreglo

    notimismensajess=(String.valueOf(notimismensajes[0]));
    //// aqui le asigno el valor a una variable String del arreglo

    //////como es null o igual si inicializo «notimismensajess2» entra al if y «notimismensajess2» toma el valor de la variable «notimismensajess»

    if(notimismensajess!=notimismensajess2)
    {
    notimismensajess2=notimismensajess;

    texto3.setText(notimismensajess2);
    }

    y si, el problema es q cuando se acaba la tarea asincrona no mantiene el valor de «notimismensajess2»

  27. 15 noviembre, 2013 a las 4:28 pm

    hay alguan forma de que en un arrayadapter pueda llamar un tas async

    • 15 noviembre, 2013 a las 5:07 pm

      Cuando crees el ArrayAdapter pásale el Async por el contructor, o puedes crear un método específicamente para ello.

      • 15 noviembre, 2013 a las 7:18 pm

        package com.elkinlrc.ordre;

        import java.util.List;

        import com.elkinlrc.ordre.TaskAsyncHandler.onlineListener;

        import android.R.integer;
        import android.app.Activity;
        import android.content.Context;
        import android.text.InputFilter.LengthFilter;
        import android.view.LayoutInflater;
        import android.view.View;
        import android.view.View.OnClickListener;
        import android.view.ViewGroup;
        import android.widget.ArrayAdapter;
        import android.widget.EditText;
        import android.widget.ImageView;

        import android.widget.TextView;

        public class ProductosAdapter extends ArrayAdapter implements onlineListener
        {
        private final Activity activity;
        private List objects;

        // ********************
        static class ListHolder
        {
        public ImageView imagen;
        public TextView nombre;
        public TextView descripcion;
        public TextView exitencia;
        public TextView valor;
        public ImageView agregar;
        public ImageView restar;
        public TextView seleccionado;
        }
        // ******************

        public ProductosAdapter(Activity activity, List objects)
        {
        super(activity, R.layout.listadoproductos_activity, objects);

        this.activity = activity;
        this.objects = objects;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent)
        {
        // *******************************************
        View v = convertView;

        if(v == null)
        {
        LayoutInflater inf = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inf.inflate(R.layout.listadoproductos_activity, null);
        }

        Productos dir = objects.get(position);
        ImageView imagen = (ImageView) v.findViewById(R.id.producto_imagen);
        imagen.setImageBitmap(dir.getImagen());

        TextView nombre = (TextView) v.findViewById(R.id.producto_nombre);
        nombre.setText(dir.getNombre());

        TextView seleccionado = (TextView)v.findViewById(R.id.producto_seleccionado);
        seleccionado.setText(Integer.toString(dir.getSeleccion()));

        TextView descripcion = (TextView) v.findViewById(R.id.producto_descripcon);
        descripcion.setText(dir.getDescripcion());

        TextView existencia = (TextView) v.findViewById(R.id.producto_existencia);
        existencia.setText(Integer.toString(dir.getExistencia()));

        TextView valor = (TextView) v.findViewById(R.id.producto_valor);
        valor.setText(«$ «+Integer.toString(dir.getValor()));
        if (dir.getExistencia()>0)
        {
        ImageView agregar = (ImageView) v.findViewById(R.id.producto_add);
        agregar.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
        // TODO Auto-generated method stub
        String url=»http://xxx.com»;
        TaskAsyncHandler productoAdd = new TaskAsyncHandler();
        //.execute(400,url);
        productoAdd.listener=this;

        productoAdd.task(400,url);
        }
        });
        agregar.setClickable(true);
        }
        ImageView restar = (ImageView) v.findViewById(R.id.producto_del);
        restar.setClickable(true);

        //NumberPicker seleccionado =(NumberPicker)v.findViewById(R.id.producto_seleccionado);
        //seleccionado.setMaxValue(dir.getExistencia());
        //seleccionado.setMinValue(0);

        return v;
        // ***********************************************
        }

        @Override
        public void respuesta(int tasks, String respuesta, Object dato) {
        // TODO Auto-generated method stub

        }
        public String tabular(String response,int cortar){
        int cantidad;
        int numero;
        String result=»»;
        cantidad=response.length();
        numero =cantidad/cortar;
        for (int i = 0; i < cantidad; i++) {
        result=result+response.substring(0,25);
        }

        return "";
        }

        }

        Buenas este es mi código actual, soy nuevo en java y en android, me podrias indicar como le paso el task al contructor gracias

      • 15 noviembre, 2013 a las 7:29 pm

        Entre tus propiedades añades:
        private AsyncTask async;

        En el constructor lo dejas algo así:

        public ProductosAdapter(Activity activity, List objects, AsyncTask async) {
        …..
        this,async = async;

        }

        Cambia los ? por lo que corresponda.

        Por curiosidad, ¿Por qué necesitas llamarlo desde un Adapter?

      • 15 noviembre, 2013 a las 8:06 pm

        jejej como te lo dije solo llevo una semana en android, y pos no se cual seria la mejor manera :/

  28. 15 noviembre, 2013 a las 8:21 pm

    el arrayAdapter tiene una lista de productos esos productos cuando le de click en add o descontar tiene que hacer una tarea, de peticion al servidor donde debe sumar o descontar

    • 15 noviembre, 2013 a las 8:28 pm

      Para eso puedes usar «OnItemSelectedListener» desde el Activity.

      En vez de asignarle un «onClick» a cada elemento, le asignas un OnItemSelecteListener al ListView, y cuando se pulse algún elemento te mandará el indice de este, con el que podrás obtener el elemento y hacer el proceso que desees.

  29. 15 noviembre, 2013 a las 8:34 pm

    A listo apenas llegue a mi casa esta noche lo voy a probar, muchas gracias por toda la ayuda prestada

  30. 16 noviembre, 2013 a las 2:36 am

    @Override
    public void onItemSelected(AdapterView arg0, View arg1, int arg2,
    long arg3) {
    // TODO Auto-generated method stub

    Toast.makeText(this,Integer.toString(arg2),Toast.LENGTH_SHORT);

    }

    @Override
    public void onNothingSelected(AdapterView arg0) {
    // TODO Auto-generated method stub

    }

    ya lo hice y me creo estos métodos, me podrias indicar como hago para indicarlo que sea cuando le doy click
    en una imagen?? del listview?’

  31. 31 May, 2014 a las 6:51 am

    Hola, este permite ser llamado varias veces?
    TareaAsync = new MiTarea();
    algo….
    MiTarea.execute;
    otra cosa….
    algo….
    MiTarea.execute;

    ???
    Gracias saludos

    • 2 junio, 2014 a las 7:26 am

      El mismo objeto sólo una vez. Tendrías que hacer algo así:

      MiTarea t1 = new MiTarea();
      t1.execute();
      algo;
      MiTarea t2 = new MiTarea();
      t2.execute();

  32. Diego Torres
    9 junio, 2014 a las 8:01 pm

    Aportazo, eso si me asombra mas tu paciencia y dedicación para responder. y para ponerla a prueba xD.
    una consulta que nadie ha hecho, a donde se van los 250 [return 250;] que se devuelven en protected Integer doInBackground(String… urls) en el ejemplo???
    no creo que en [new MiTarea().execute(«http://www.ejemplo.com/file.zip»);] ya que perderia lo asyncronico.
    saludos!

    • 9 junio, 2014 a las 8:06 pm

      Lo que devuelve doInBackground le llega por parámetro a onPostExecute

  33. Diego Torres
  34. Potter
    30 junio, 2014 a las 10:14 pm

    Muchas gracias, me ha sido de mucha utilidad 🙂

  35. 7 agosto, 2014 a las 5:55 pm

    Muy bien explicado, felicidades : )

  1. 25 May, 2011 a las 3:09 pm
  2. 1 agosto, 2013 a las 6:56 pm
  3. 5 septiembre, 2013 a las 6:52 am

Replica a aqpalex87lex Cancelar la respuesta