Únete a ⁠ #Android11: The Beta Launch Show el 3 de junio.

Cómo ejecutar subprocesos en Worker

Cuando usas un Worker, WorkManager llama automáticamente a Worker.doWork() en un subproceso en segundo plano. El subproceso en segundo plano proviene del Executor que se especificó en Configuration de WorkManager. De forma predeterminada, WorkManager configura un Executor por ti, pero también puedes personalizar el tuyo. Por ejemplo, puedes compartir un Executor existente en segundo plano en la app o crear un Executor de un solo subproceso para asegurarte de que todas las tareas en segundo plano se ejecuten en serie, o incluso especificar un ThreadPool con un recuento de subprocesos diferente. Para personalizar el Executor, asegúrate de haber habilitado la inicialización manual de WorkManager. Cuando configuras WorkManager, puedes especificar tu Executor de la siguiente manera:

Kotlin

    WorkManager.initialize(
        context,
        Configuration.Builder()
            .setExecutor(Executors.newFixedThreadPool(8))
            .build())
    

Java

    WorkManager.initialize(
        context,
        new Configuration.Builder()
            .setExecutor(Executors.newFixedThreadPool(8))
            .build());
    

A continuación, se muestra un ejemplo de un trabajador simple que descarga el contenido de algunos sitios web de forma secuencial:

Kotlin

    class DownloadWorker(context: Context, params: WorkerParameters) : Worker(context, params) {

        override fun doWork(): ListenableWorker.Result {
            for (i in 0..99) {
                try {
                    downloadSynchronously("https://www.google.com")
                } catch (e: IOException) {
                    return ListenableWorker.Result.failure()
                }
            }

            return ListenableWorker.Result.success()
        }
    }
    

Java

    public class DownloadWorker extends Worker {

        public DownloadWorker(Context context, WorkerParameters params) {
            super(context, params);
        }

        @NonNull
        @Override
        public Result doWork() {
            for (int i = 0; i < 100; ++i) {
                try {
                    downloadSynchronously("https://www.google.com");
                } catch (IOException e) {
                    return Result.failure();
                }
            }

            return Result.success();
        }

    }

    

Ten en cuenta que Worker.doWork() es una llamada síncrona; se espera que hagas todas las tareas en segundo plano de forma bloqueada, y que finalices cuando el método se cierre. Si llamas a una API asíncrona en doWork() y devuelves un Result, es posible que la devolución de llamada no funcione correctamente. Si te encuentras con esta situación, considera usar un ListenableWorker (consulta Cómo ejecutar subprocesos en ListenableWorker).

Cuando un Worker que está en ejecución se detiene por algún motivo, recibe una llamada a Worker.onStopped(). Anula este método o llama a Worker.isStopped() para establecer un punto de control de tu código y liberar recursos según sea necesario. Cuando se detiene Worker en el ejemplo anterior, puede estar en el medio de su bucle de descarga de elementos, y continuará haciéndolo aunque se haya detenido. Para optimizar este comportamiento, puedes hacer lo siguiente:

Kotlin

    class DownloadWorker(context: Context, params: WorkerParameters) : Worker(context, params) {

        override fun doWork(): ListenableWorker.Result {
            for (i in 0..99) {
                if (isStopped) {
                    break
                }

                try {
                    downloadSynchronously("https://www.google.com")
                } catch (e: IOException) {
                    return ListenableWorker.Result.failure()
                }

            }

            return ListenableWorker.Result.success()
        }
    }
    

Java

    public class DownloadWorker extends Worker {

        public DownloadWorker(Context context, WorkerParameters params) {
            super(context, params);
        }

        @NonNull
        @Override
        public Result doWork() {
            for (int i = 0; i < 100; ++i) {
                if (isStopped()) {
                    break;
                }

                try {
                    downloadSynchronously("https://www.google.com");
                } catch (IOException e) {
                    return Result.failure();
                }
            }

            return Result.success();
        }
    }
    

Una vez que se detiene un Worker, no importa lo que muestres de Worker.doWork(); el Result se ignorará.