En el desarrollo de aplicaciones Android, es común que necesitemos realizar tareas que pueden llevar tiempo, como descargar datos de la web, procesar imágenes o realizar cálculos complejos. Ejecutar estas tareas en el hilo principal puede hacer que la aplicación se vuelva lenta o incluso se bloquee. Para evitar esto, Android proporciona varias formas de manejar tareas en segundo plano.
Conceptos Clave
- Hilos (Threads): La forma más básica de ejecutar tareas en segundo plano.
- AsyncTask: Una clase que facilita la ejecución de tareas en segundo plano y la actualización de la interfaz de usuario.
- WorkManager: Una API más moderna y robusta para manejar tareas en segundo plano que necesitan ser ejecutadas de manera confiable.
- JobScheduler: Una API para programar tareas que deben ejecutarse en momentos específicos o bajo ciertas condiciones.
Hilos (Threads)
Ejemplo Básico
new Thread(new Runnable() { @Override public void run() { // Código que se ejecutará en segundo plano // Por ejemplo, descargar datos de una URL String data = downloadDataFromUrl("https://example.com/data"); // Actualizar la interfaz de usuario runOnUiThread(new Runnable() { @Override public void run() { // Código para actualizar la UI textView.setText(data); } }); } }).start();
Explicación
- new Thread(new Runnable() { ... }).start();: Crea y empieza un nuevo hilo.
- runOnUiThread(new Runnable() { ... });: Permite actualizar la interfaz de usuario desde el hilo principal.
AsyncTask
Ejemplo Básico
private class DownloadTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... urls) { // Código que se ejecutará en segundo plano return downloadDataFromUrl(urls[0]); } @Override protected void onPostExecute(String result) { // Código para actualizar la UI textView.setText(result); } } // Ejecutar la tarea new DownloadTask().execute("https://example.com/data");
Explicación
- doInBackground(String... urls): Método donde se ejecuta la tarea en segundo plano.
- onPostExecute(String result): Método que se ejecuta en el hilo principal después de que
doInBackground
ha terminado.
WorkManager
Ejemplo Básico
- Dependencia en build.gradle
- Definir una clase Worker
public class DownloadWorker extends Worker { public DownloadWorker(@NonNull Context context, @NonNull WorkerParameters params) { super(context, params); } @NonNull @Override public Result doWork() { // Código que se ejecutará en segundo plano String data = downloadDataFromUrl("https://example.com/data"); // Guardar los datos en Data para pasarlos a la UI Data outputData = new Data.Builder() .putString("data", data) .build(); return Result.success(outputData); } }
- Programar la tarea
WorkRequest downloadWorkRequest = new OneTimeWorkRequest.Builder(DownloadWorker.class).build(); WorkManager.getInstance(context).enqueue(downloadWorkRequest);
- Obtener el resultado
WorkManager.getInstance(context).getWorkInfoByIdLiveData(downloadWorkRequest.getId()) .observe(this, workInfo -> { if (workInfo != null && workInfo.getState().isFinished()) { String data = workInfo.getOutputData().getString("data"); textView.setText(data); } });
Explicación
- Worker: Clase que define la tarea en segundo plano.
- WorkRequest: Objeto que programa la tarea.
- WorkManager: API que gestiona la ejecución de la tarea.
JobScheduler
Ejemplo Básico
- Definir un JobService
public class DownloadJobService extends JobService { @Override public boolean onStartJob(JobParameters params) { new Thread(new Runnable() { @Override public void run() { // Código que se ejecutará en segundo plano String data = downloadDataFromUrl("https://example.com/data"); // Actualizar la interfaz de usuario runOnUiThread(new Runnable() { @Override public void run() { textView.setText(data); } }); // Indicar que el trabajo ha terminado jobFinished(params, false); } }).start(); return true; } @Override public boolean onStopJob(JobParameters params) { return false; } }
- Programar el trabajo
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); JobInfo jobInfo = new JobInfo.Builder(1, new ComponentName(this, DownloadJobService.class)) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) .build(); jobScheduler.schedule(jobInfo);
Explicación
- JobService: Clase que define la tarea en segundo plano.
- JobScheduler: API que programa y gestiona la ejecución de la tarea.
Ejercicio Práctico
Ejercicio
- Crea una aplicación que descargue datos de una URL en segundo plano y los muestre en un
TextView
. - Implementa la descarga usando
WorkManager
.
Solución
- Dependencia en build.gradle
- Definir la clase Worker
public class DownloadWorker extends Worker { public DownloadWorker(@NonNull Context context, @NonNull WorkerParameters params) { super(context, params); } @NonNull @Override public Result doWork() { String data = downloadDataFromUrl("https://example.com/data"); Data outputData = new Data.Builder() .putString("data", data) .build(); return Result.success(outputData); } }
- Programar la tarea
WorkRequest downloadWorkRequest = new OneTimeWorkRequest.Builder(DownloadWorker.class).build(); WorkManager.getInstance(context).enqueue(downloadWorkRequest);
- Obtener el resultado
WorkManager.getInstance(context).getWorkInfoByIdLiveData(downloadWorkRequest.getId()) .observe(this, workInfo -> { if (workInfo != null && workInfo.getState().isFinished()) { String data = workInfo.getOutputData().getString("data"); textView.setText(data); } });
Conclusión
En esta sección, hemos aprendido cómo manejar tareas en segundo plano en Android utilizando diferentes enfoques como Hilos, AsyncTask, WorkManager y JobScheduler. Cada método tiene sus propias ventajas y desventajas, y la elección del método adecuado dependerá de los requisitos específicos de tu aplicación. Con estos conocimientos, estarás mejor preparado para crear aplicaciones Android eficientes y responsivas.
Curso de Android Studio
Módulo 1: Introducción a Android Studio
- Introducción a Android Studio
- Configuración de Android Studio
- Entendiendo la interfaz de Android Studio
- Creando tu primer proyecto Android
Módulo 2: Desarrollo básico de Android
- Entendiendo la estructura del proyecto Android
- Introducción a los diseños XML
- Componentes básicos de la interfaz de usuario
- Introducción a las actividades
- Ejecutando tu aplicación en un emulador
Módulo 3: Desarrollo intermedio de Android
- Introducción a los Intents
- Trabajando con Fragmentos
- Manejo de la entrada del usuario
- Usando RecyclerView
- Redes en Android
Módulo 4: Desarrollo avanzado de Android
- Persistencia de datos con SQLite
- Usando Room para la gestión de bases de datos
- Componentes avanzados de la interfaz de usuario
- Vistas personalizadas y Canvas
- Trabajando con tareas en segundo plano
Módulo 5: Desarrollo profesional de Android
- Implementando la arquitectura MVVM
- Inyección de dependencias con Dagger
- Pruebas unitarias y pruebas de interfaz de usuario
- Publicando tu aplicación en Google Play
- Optimización del rendimiento