Worker でのスレッド化

Worker を使用すると、WorkManager がバックグラウンド スレッドで自動的に Worker.doWork() を呼び出します。バックグラウンド スレッドは、WorkManager の Configuration で指定された Executor で生成されます。デフォルトでは、WorkManager が 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());

以下に、ウェブページのコンテンツを 100 回ダウンロードするシンプルな Worker の例を示します。

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() は同期呼び出しです。バックグラウンド処理全体をブロック方式で行い、メソッドが終了するまでに処理が完了することが求められます。doWork() で非同期 API を呼び出し、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 は無視されるようになります。