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

Когда вы используете 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 (см. Потоки в ListenableWorker ).

Когда работающий в данный момент Worker останавливается по какой-либо причине , он получает вызов Worker.onStopped() . Переопределите этот метод или вызовите 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 будет проигнорирован.