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

  1. Hilos (Threads): La forma más básica de ejecutar tareas en segundo plano.
  2. AsyncTask: Una clase que facilita la ejecución de tareas en segundo plano y la actualización de la interfaz de usuario.
  3. WorkManager: Una API más moderna y robusta para manejar tareas en segundo plano que necesitan ser ejecutadas de manera confiable.
  4. 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

  1. Dependencia en build.gradle
dependencies {
    implementation "androidx.work:work-runtime:2.7.0"
}
  1. 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);
    }
}
  1. Programar la tarea
WorkRequest downloadWorkRequest = new OneTimeWorkRequest.Builder(DownloadWorker.class).build();
WorkManager.getInstance(context).enqueue(downloadWorkRequest);
  1. 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

  1. 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;
    }
}
  1. 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

  1. Crea una aplicación que descargue datos de una URL en segundo plano y los muestre en un TextView.
  2. Implementa la descarga usando WorkManager.

Solución

  1. Dependencia en build.gradle
dependencies {
    implementation "androidx.work:work-runtime:2.7.0"
}
  1. 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);
    }
}
  1. Programar la tarea
WorkRequest downloadWorkRequest = new OneTimeWorkRequest.Builder(DownloadWorker.class).build();
WorkManager.getInstance(context).enqueue(downloadWorkRequest);
  1. 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.

© Copyright 2024. Todos los derechos reservados