Como criar threads no Worker

Quando você usa um Worker, o WorkManager chama Worker.doWork() automaticamente em uma linha de execução em segundo plano. A linha de execução em segundo plano vem do Executor especificado na Configuration do WorkManager. Por padrão, o WorkManager configura um Executor para você, mas também é possível personalizar o seu. Por exemplo, você pode compartilhar um Executor de segundo plano existente no seu app, criar um Executor de linha de execução única para garantir que todo o trabalho em segundo plano seja executado sequencialmente ou até mesmo especificar um Executor personalizado. Para personalizar o Executor, inicialize o WorkManager manualmente.

Ao configurar o WorkManager manualmente, você pode especificar o Executor da seguinte maneira:

Kotlin

WorkManager.initialize(
    context,
    Configuration.Builder()
         // Uses a fixed thread pool of size 8 threads.
        .setExecutor(Executors.newFixedThreadPool(8))
        .build())

Java

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

Veja um exemplo de um Worker simples que faz o download do conteúdo de uma página da Web 100 vezes:

Kotlin

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

    override fun doWork(): ListenableWorker.Result {
        repeat(100) {
            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();
    }

}

Observe que Worker.doWork() é uma chamada síncrona. Espera-se que você faça todo o trabalho em segundo plano de maneira bloqueada e termine no momento em que o método for encerrado. Se você chamar uma API assíncrona no doWork() e retornar um Result, seu callback poderá não funcionar corretamente. Se você estiver nessa situação, use um ListenableWorker. Consulte Threads no ListableWorker.

Quando um Worker em execução é interrompido por qualquer motivo, ele recebe uma chamada para Worker.onStopped(). Substitua esse método ou chame Worker.isStopped() para verificar seu código e liberar recursos quando necessário. Quando o Worker do exemplo acima for interrompido, ele poderá estar no meio do loop de download de itens e continuará fazendo isso. Para otimizar esse comportamento, você pode fazer algo parecido com o seguinte:

Kotlin

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

    override fun doWork(): ListenableWorker.Result {
        repeat(100) {
            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();
    }
}

Depois que um Worker for interrompido, independentemente do que Worker.doWork() retornar, o Result será ignorado.