WorkManager は、非同期タスクのスケジュールを簡単に設定するための一連の API を提供します。これにより、アプリが閉じられた場合やデバイスが再起動した場合にも実行されることが期待されるタスクを即時実行または遅延実行できます。また、WorkManager は Kotlin ユーザーに最大級のコルーチンのサポートを提供します。この投稿では、WorkManager Codelab の内容に基づいて、WorkManager とコルーチンの基本について説明します。では早速始めましょう。
ユーザーが特定の画面から離れたり、アプリがバックグラウンド状態になったり、デバイスが再起動したりしても実行を続ける必要があるタスクには、WorkManager ライブラリを使うことが推奨されています。一般的には、以下のようなタスクが考えられます。
ユーザーが画面などの特定のスコープを離れたときに即時実行したタスクが終了する可能性がある場合は、直接 Kotlin コルーチンを使うことを推奨します。
WorkManager Codelab では、画像をぼかしてその結果をディスクに保存します。これを実現するために必要なことを確認しましょう。
まず、work-runtime-ktx 依存性を追加しました。
implementation "androidx.work:work-runtime-ktx:$work_version"
そして、独自の Worker クラスを実装します。ここに、バックグラウンドで実行する実際の作業に必要なコードを含めます。Worker クラスを拡張し、doWork() メソッドをオーバーライドします。これは一番重要なクラスなので、のちほど詳しく説明します。最初の実装は次のようになります。
次に、作業のリクエストを作成します。今回の場合は、作業を一度だけ行いたいので、OneTimeWorkRequest.Builder を使います。入力として、ぼかしたい画像の Uri を設定します。
Kotlin のヒント: 入力データを作成するために、workDataOf 関数を使うことができます。この関数は、データビルダーを作成し、キーと値のペアを格納してデータを作成します。
作業のスケジュールを設定して実行するには、WorkManager クラスを使います。その際に、実行するタスクと、タスクへの制約を指定できます。
Worker を使うと、WorkManager は自動的にバックグラウンド スレッドで Worker.doWork() を呼び出します。doWork() から返される Result は、WorkManager サービスに作業が成功したかどうかと、失敗した場合には作業を再試行すべきかどうかを通知します。
Worker.doWork() は同期呼び出しです。バックグラウンドの作業全体をブロックありで実行し、メソッドが終了するときには完了していることになります。doWork() で非同期 API を呼び出して Result を返すと、コールバックが正しく動作しない場合があります。
もう少し複雑な例として、ぼかしをかけたすべてのファイルの Uri をデータベースに保存する場合を考えてみましょう。
これを実現するために、以下を作成しました。
実装はこちらをご覧ください。
Kotlin でデータベースへのデータの保存やネットワーク リクエストなどの非同期作業を行う必要がある場合は、CoroutineWorker の利用を推奨します。
CoroutineWorker を使うと、Kotlin コルーチンを使って非同期作業を行えます。
doWork() メソッドは suspend メソッドです。つまり、中断を伴う dao を簡単に呼び出すことができます。
デフォルトで、doWork() は Dispatchers.Default を使います。この動作は必要な Dispatcher でオーバーライドできます。今回は、既に Room が挿入作業を別の Dispatcher に移動させているので、これを行う必要はありません。詳しくは、Room Kotlin API の投稿をご覧ください。
ぜひ CoroutineWorker を使って、ユーザーがアプリを閉じても完了しなければならない非同期作業を実行してみてください。
WorkManager についてもっと詳しく知りたい方は、今後のシリーズで詳しく解説しますので、ご期待ください。それまでの間は、Codelab やドキュメントをご覧ください。