O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Threads no ListenableWorker

Em determinadas situações, talvez seja necessário oferecer uma estratégia personalizada para linhas de execução. Por exemplo, você pode precisar processar uma operação assíncrona baseada em callback. Nesse caso, não é possível simplesmente confiar em um Worker, porque ele não pode fazer o trabalho de forma bloqueada. O WorkManager é compatível com esse caso de uso com ListenableWorker. ListenableWorker é a API do worker de nível mais baixo. Worker, CoroutineWorker e RxWorker são derivadas dessa classe. Um ListenableWorker indica apenas quando o trabalho precisa iniciar e parar, deixando toda a linha de execução por sua conta. O sinal de início do trabalho é invocado na linha de execução principal, por isso, é muito importante que você vá manualmente a uma linha de execução em segundo plano da sua escolha.

O método abstrato ListenableWorker.startWork() retorna um ListenableFuture do Result. Um ListenableFuture é uma interface leve: é um Future que fornece funcionalidade para anexar listeners e propagar exceções. No método startWork, você precisa retornar um ListenableFuture, que será definido com o Result da operação assim que ela for concluída. É possível criar ListenableFutures de duas formas:

  1. Se você usa Guava, use ListeningExecutorService.
  2. Caso contrário, inclua councurrent-futures no arquivo do Gradle e use CallbackToFutureAdapter.

Se você quer executar algum trabalho com base em um callback assíncrono, faça algo parecido com isto:

public class CallbackWorker extends ListenableWorker {

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

    @NonNull
    @Override
    public ListenableFuture<Result> startWork() {
        return CallbackToFutureAdapter.getFuture(completer -> {
            Callback callback = new Callback() {
                int successes = 0;

                @Override
                public void onFailure(Call call, IOException e) {
                    completer.setException(e);
                }

                @Override
                public void onResponse(Call call, Response response) {
                    ++successes;
                    if (successes == 100) {
                        completer.set(Result.success());
                    }
                }
            };

            for (int i = 0; i < 100; ++i) {
                downloadAsynchronously("https://www.google.com", callback);
            }
            return callback;
        });
    }
}

O que acontecerá se seu trabalho for interrompido? O ListenableFuture de um ListenableWorker é sempre cancelado quando o trabalho é interrompido. Usando um CallbackToFutureAdapter, basta adicionar um listener de cancelamento da seguinte forma:

public class CallbackWorker extends ListenableWorker {

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

    @NonNull
    @Override
    public ListenableFuture<Result> startWork() {
        return CallbackToFutureAdapter.getFuture(completer -> {
            Callback callback = new Callback() {
                int successes = 0;

                @Override
                public void onFailure(Call call, IOException e) {
                    completer.setException(e);
                }

                @Override
                public void onResponse(Call call, Response response) {
                    ++successes;
                    if (successes == 100) {
                        completer.set(Result.success());
                    }
                }
            };

            completer.addCancellationListener(cancelDownloadsRunnable, executor);

            for (int i = 0; i < 100; ++i) {
                downloadAsynchronously("https://www.google.com", callback);
            }
            return callback;
        });
    }
}