Threading in Worker

Wenn Sie einen Worker verwenden, ruft WorkManager automatisch Worker.doWork() in einem Hintergrundthread auf. Der Hintergrundthread stammt aus dem Executor, der in Configuration von WorkManager angegeben ist. Standardmäßig richtet WorkManager eine Executor für Sie ein. Sie können diese aber auch selbst festlegen. Sie können beispielsweise einen vorhandenen Hintergrund-Executor in Ihrer Anwendung freigeben, einen Executor mit einem einzigen Thread erstellen, um dafür zu sorgen, dass alle Hintergrundarbeiten nacheinander ausgeführt werden, oder sogar eine benutzerdefinierte Executor angeben. Wenn Sie Executor anpassen möchten, müssen Sie WorkManager manuell initialisieren.

Bei der manuellen Konfiguration von WorkManager können Sie den Executor so angeben:

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

Hier ist ein Beispiel für ein einfaches Worker-Element, mit dem der Inhalt einer Webseite 100 Mal heruntergeladen wird:

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() ist ein synchroner Aufruf. Es wird erwartet, dass Sie die gesamte Hintergrundarbeit blockieren und bis zum Ende der Methode abschließen. Wenn Sie eine asynchrone API in doWork() aufrufen und ein Result zurückgeben, funktioniert Ihr Callback möglicherweise nicht ordnungsgemäß. In dieser Situation empfiehlt sich die Verwendung eines ListenableWorker (siehe Threading in ListenableWorker).

Wenn eine derzeit ausgeführte Worker aus irgendeinem Grund beendet wird, erhält sie einen Aufruf an Worker.onStopped(). Überschreiben Sie diese Methode oder rufen Sie Worker.isStopped() auf, um Ihren Code zu prüfen und bei Bedarf Ressourcen freizugeben. Wenn das Worker im Beispiel oben gestoppt wird, befindet es sich möglicherweise mitten in seiner Schleife des Herunterladens von Elementen. Dies wird fortgesetzt, obwohl der Vorgang angehalten wurde. Um dieses Verhalten zu optimieren, können Sie beispielsweise Folgendes tun:

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

Wenn ein Worker gestoppt wurde, spielt es keine Rolle, was von Worker.doWork() zurückgegeben wird. Das Result wird ignoriert.