Потоки в Worker

При использовании Worker WorkManager автоматически вызывает Worker.doWork() в фоновом потоке. Фоновый поток поступает из Executor, указанного в Configuration WorkManager. По умолчанию WorkManager настраивает для вас Executor, но вы также можете настроить свой собственный. Например, вы можете использовать существующий фоновый Executor в своем приложении, создать однопоточный Executor, чтобы все фоновые задачи выполнялись последовательно, или даже указать собственный Executor. Чтобы настроить Executor, инициализируйте WorkManager вручную.

При настройке WorkManager вручную вы можете указать Executor следующим образом:

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());

Вот пример простого Worker, который скачивает содержимое веб-страницы 100 раз:

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();
    }

}

Обратите внимание, что Worker.doWork() – это синхронный вызов. Вам нужно выполнить всю фоновую работу в блокирующем режиме и завершить ее к моменту выхода из метода. Если вы вызываете асинхронный API в doWork() и возвращаете Result, обратный вызов может работать неправильно. В этом случае можно использовать ListenableWorker (см. Потоки в ListenableWorker).

Когда работающий в данный момент экземпляр Worker останавливается по какой-либо причине, он получает вызов Worker.onStopped(). Переопределите этот метод или вызовите Worker.isStopped(), чтобы создать контрольную точку в коде и при необходимости освободить ресурсы. Если остановить Worker из примера выше, он может находиться в середине цикла скачивания элементов и продолжит делать это, даже если он был остановлен. Чтобы оптимизировать этот процесс, вы можете сделать следующее:

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();
    }
}

После остановки Worker не имеет значения, что возвращает Worker.doWork(), так как Result будет игнорироваться.