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(); } } }
Me ha servido de mucho. Lo usé para mi primera aplicación:
Muchísimas gracias por el post… 😉
así de simple es como se debe explicar en un blog, muy buen post!!
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..
por cierto ya lo probé de las 2 formas y las 2 se comportan igual
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.
Muy bien explicado. Gracias
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?
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í.
Aquí tienes otro tutorial muy bueno:
http://blog.netbyt.es/post/2011/09/04/Disenar-con-capacidad-de-respuesta-(parte-3).aspx
Me ha parecido genial. Funciona a las 1000 maravillas y es fácil de entender. Muchas gracias
Muy buen post, me sirvió mucho.
Muchas gracias.
Muy claro ha quedado. Lo probaré. Muchas gracias.
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.
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].
muchas gracias no me habia fijado en eso.
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.
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);
}
Muchas gracias
Enhorabuena por el artículo, funciona de maravilla y muy bien explicado. Así da gusto.
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
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.
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
Donde has creado el AsyncTask? Yo suelo crearlo dentro del propio activity y así acceder a los datos.
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
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.
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
MUCHAS GRACIAS!
Perfectamente explicado y funciona muy bien!
Había estado buscando algo como ésto por días.
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!
Excelente!! muchas gracias
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?
Puedes ejecutarla desde donde quieras
¿Y como lo hago para escribir en un textview en la actividad principal?
Perfecto. Es justo lo que buscaba.
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
Pues sin ver el código no tengo ni idea. Puede haber miles de motivios
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;
}
}
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
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)
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??
No pongas la variable dentro del AsyncTask, ponla en la clase «padre».
/////////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
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?
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»
hay alguan forma de que en un arrayadapter pueda llamar un tas async
Cuando crees el ArrayAdapter pásale el Async por el contructor, o puedes crear un método específicamente para ello.
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
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?
jejej como te lo dije solo llevo una semana en android, y pos no se cual seria la mejor manera
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
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.
A listo apenas llegue a mi casa esta noche lo voy a probar, muchas gracias por toda la ayuda prestada
@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?’
Hola, este permite ser llamado varias veces?
TareaAsync = new MiTarea();
algo….
MiTarea.execute;
otra cosa….
algo….
MiTarea.execute;
…
???
Gracias saludos
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();
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!
Lo que devuelve doInBackground le llega por parámetro a onPostExecute
http://automovilescolombia.com/foros/attachments/mrburns-excelente-jpg.74906/
(y)
Muchas gracias, me ha sido de mucha utilidad 🙂
Muy bien explicado, felicidades : )