Потоки в работнике

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

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

Котлин

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

Ява

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

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

Котлин

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

Ява

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 (см. Поток в прослушивании ).

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

Котлин

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

Ява

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 будет проигнорирован.