Exécuter des threads dans un worker

Lorsque vous utilisez un Worker, WorkManager appelle automatiquement Worker.doWork() sur un thread d'arrière-plan. Le thread d'arrière-plan provient de l'Executor spécifié dans la Configuration de WorkManager. Par défaut, WorkManager configure un Executor pour vous, mais vous pouvez également personnaliser le vôtre. Par exemple, vous pouvez partager un exécuteur d'arrière-plan existant dans votre application, créer un Executor à thread unique pour vous assurer que tout le travail en arrière-plan s'exécute de manière séquentielle, ou même spécifier un Executor personnalisé. Pour personnaliser un Executor, veillez à initialiser WorkManager manuellement.

Lorsque vous configurez WorkManager manuellement, vous pouvez spécifier un Executor comme suit :

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

Voici un exemple de Worker simple qui télécharge le contenu d'une page Web 100 fois :

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

}

Notez que Worker.doWork() est un appel synchrone. Vous devez effectuer la totalité de votre travail d'arrière-plan de manière bloquante et le terminer lorsque la méthode est finie. Si vous appelez une API asynchrone dans doWork() et que vous renvoyez un objet Result, votre rappel risque de ne pas fonctionner correctement. Si vous vous trouvez dans cette situation, envisagez d'utiliser un ListenableWorker (consultez Threading in listeningableWorker, soit "Exécuter des threads dans listeningableWorker").

Lorsqu'un Worker en cours d'exécution est arrêté pour une raison quelconque, il reçoit un appel à Worker.onStopped(). Ignorez cette méthode ou appelez Worker.isStopped() pour vérifier votre code et libérer des ressources si nécessaire. Lorsque le Worker est arrêté dans l'exemple ci-dessus, il se peut qu'il soit au milieu de la boucle de téléchargement des éléments et continue de le faire même s'il a été arrêté. Pour optimiser ce comportement, vous pouvez procéder comme suit :

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

Une fois qu'un Worker est arrêté, peu importe ce que vous renvoyez à partir de Worker.doWork(). Le Result sera ignoré.