Blog >Lista Soluciones > AsyncTask : lanzar segundo hilo
Lanzar un segundo hilo
Todos los componentes de una aplicación Android, tanto las actividades, los servicios o los broadcast receivers que se ejecutan en el mismo hilo de ejecución, el hilo principal. Cualquier operación larga o costosa que realicemos en este hilo va a bloquear la ejecución del resto de componentes de la aplicación, produciendo al usuario un efecto evidente de lentitud o bloqueo.
Y como no queremos que nos ocurra, vamos a usar hilos segundarios para ejecutar las operaciones tan "costosas" :
Creamos un nuevo proyecto y colocamos un botón y un ProgressBar en nuestra actividad :
y en el onCreate() de nuestra actividad principal, les hacemos referencia :
Ahora, haremos una función que nos haga esperar un segundo cuando hagamos click en el botón, que se llamará desde esta otra que irá dentro del onClick de nuestro botón :
Ejecutamos la aplicación para observar el resultado, de momento el efecto no es el deseado, se ha quedado colgada y a los 10 segundos se ha llenado, esto es porque esta corriendo en el hilo principal.Ahora vemos el método thread, que internamente tiene el run() :
El código entero :
Ahora sí podemos ver el progreso de nuestro progressBar. La creación de otro hilo nos ha permitido mantener el hilo principal libre para que nuestra interfaz de usuario se actualize durante la ejecución de la tarea en segundo plano.
AsyncTask
Ahora vamos a ver AsynkTask, esta clase es menos engorroso y más práctico.Si quereis ver más información, ya que yo me enfoco sólo en el ámbito práctico del código y quereis curiosear podeis meteros aquí.
La forma más básica de usar la clase AsyncTask consiste en crear una nueva clase que extienda de ella y sobrescribir varios de sus métodos :
AsyncTask nos permite un uso fácil del hilo, permitiendonos realizar procesos en background y publicandolos posteriormente sin necesidad de usar handlers. Son tareas asíncronas : Estas tareas asíncronas se definen con tres tipos, llamados Params, Progress y Result, y cuatro métodos, onPreExecute, doInBackground, onProgressUpdate y onPostExecute. Por ejemplo, para cargar los elementos en un ListView :
Para llamarla...
O por ejemplo, para cargar una foto a traves de Internet por medio de un enlace :
Para llamarla...
Lanzar un segundo hilo
Todos los componentes de una aplicación Android, tanto las actividades, los servicios o los broadcast receivers que se ejecutan en el mismo hilo de ejecución, el hilo principal. Cualquier operación larga o costosa que realicemos en este hilo va a bloquear la ejecución del resto de componentes de la aplicación, produciendo al usuario un efecto evidente de lentitud o bloqueo.
Y como no queremos que nos ocurra, vamos a usar hilos segundarios para ejecutar las operaciones tan "costosas" :
Creamos un nuevo proyecto y colocamos un botón y un ProgressBar en nuestra actividad :
y en el onCreate() de nuestra actividad principal, les hacemos referencia :
b1=(Button) findViewById(R.id.button1); progress= (ProgressBar) findViewById(R.id.progressBar1); progress.setMax(100); progress.setProgress(0); b1.setOnClickListener(new OnClickListener(){ @Override public void onClick(View arg0) { // TODO Auto-generated method stub } });
Ahora, haremos una función que nos haga esperar un segundo cuando hagamos click en el botón, que se llamará desde esta otra que irá dentro del onClick de nuestro botón :
public void onClick(View arg0) { reiterarHilo(); } public void reiterarHilo(){ for(int x=1; x<=10; x++) { hilounseg(); progress.incrementProgressBy(10); } } public void hilounseg(){ try { Thread.sleep(1000); } catch(InterruptedException e) {} }
Ejecutamos la aplicación para observar el resultado, de momento el efecto no es el deseado, se ha quedado colgada y a los 10 segundos se ha llenado, esto es porque esta corriendo en el hilo principal.Ahora vemos el método thread, que internamente tiene el run() :
new Thread(new Runnable() { public void run() { //COMIENZO DE OTRO HILO } }).start();
El código entero :
public class MainActivity extends Activity { private Button b1; private ProgressBar progress; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); b1=(Button) findViewById(R.id.button1); progress= (ProgressBar) findViewById(R.id.progressBar1); //LIMITES progress.setMax(100); progress.setProgress(0); b1.setOnClickListener(new OnClickListener(){ @Override public void onClick(View arg0) { new Thread(new Runnable() { public void run() { //COMIENZO HILO EN SEGUNDO PLANO reiterarHilo(); } public void post(){ } }).start(); } }); } public void reiterarHilo(){ for(int x=1; x<=10; x++) { hilounseg(); progress.incrementProgressBy(10); } } public void hilounseg(){ try { //ESTA ES LA LINEA QUE NOS HACE ESPERAR UN SEGUNDO Thread.sleep(1000); } catch(InterruptedException e) {} } }
Ahora sí podemos ver el progreso de nuestro progressBar. La creación de otro hilo nos ha permitido mantener el hilo principal libre para que nuestra interfaz de usuario se actualize durante la ejecución de la tarea en segundo plano.
AsyncTask
Ahora vamos a ver AsynkTask, esta clase es menos engorroso y más práctico.Si quereis ver más información, ya que yo me enfoco sólo en el ámbito práctico del código y quereis curiosear podeis meteros aquí.
La forma más básica de usar la clase AsyncTask consiste en crear una nueva clase que extienda de ella y sobrescribir varios de sus métodos :
- onPreExecute() : Se ejecutará antes del código principal de nuestra tarea.
- doInBackground() : Contendrá el código principal de nuestra tarea.
- onProgressUpdate() : Se ejecutará cada vez que llamemos al método publicProgrees() desde el método doInBackground().
- onPostExecute() : Se ejecutará al finalizar la tarea o tras la finalización de doInBackground().
- onCancelled() : Se ejecutará cuando se cancele la ejecución de la tarea antes de su finalización normal.
AsyncTask nos permite un uso fácil del hilo, permitiendonos realizar procesos en background y publicandolos posteriormente sin necesidad de usar handlers. Son tareas asíncronas : Estas tareas asíncronas se definen con tres tipos, llamados Params, Progress y Result, y cuatro métodos, onPreExecute, doInBackground, onProgressUpdate y onPostExecute. Por ejemplo, para cargar los elementos en un ListView :
private class ListViewTask extends AsyncTask>{ Context context; ProgressDialog pDialog; //CONSTRUCTOR public CargarListView(Context context){ this.context = context; } @Override protected void onPreExecute() { // TODO Auto-generated method stub super.onPreExecute(); pDialog = new ProgressDialog(context); pDialog.setMessage("Cargando"); pDialog.setCancelable(true); pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); pDialog.show(); } @Override protected ArrayAdapter<String> doInBackground(Void... arg0) { // TODO Auto-generated method stub try{ Thread.sleep(2000); }catch(Exception ex){ ex.printStackTrace(); } ArrayAdapter adaptador = new ArrayAdapter (context, android.R.layout.simple_list_item_1, sistemas); return adaptador; } @Override protected void onPostExecute(ArrayAdapter result) { // TODO Auto-generated method stub super.onPostExecute(result); list.setAdapter(result); pDialog.dismiss(); } }
Para llamarla...
new CargarListViewTask(activity).execute();
O por ejemplo, para cargar una foto a traves de Internet por medio de un enlace :
class DownloadImageTask extends AsyncTask{ ImageView bmImage; public DownloadImageTask(ImageView bmImage) { this.bmImage = bmImage; } @Override protected Bitmap doInBackground(String... urls) { String urldisplay = urls[0]; Bitmap mIcon11 = null; try { InputStream in = new java.net.URL(urldisplay).openStream(); mIcon11 = BitmapFactory.decodeStream(in); } catch (Exception e) { Log.e("Error", e.getMessage()); e.printStackTrace(); } return mIcon11; } @Override protected void onPostExecute(Bitmap result) { bmImage.setImageBitmap(result); } } }
Para llamarla...
new DownloadImageTask(R.id.image).execute("http//:miImagenColgada.jpg");