見出し画像

「COMPOSE を用いた ANDROID アプリ開発の基礎」の学習支援⑳ -ユニット7パスウェイ1

皆さん、こんにちは!又はこんばんは!初めての方は初めまして!
Google Codelabsの「COMPOSE を用いた ANDROID アプリ開発の基礎」コースのお手伝いをする「りおん」です。
今回は、ユニット7「WorkManager」のパスウェイ1「WorkManagerでタスクのスケジュールを設定する」です。

この記事はCodelabsの補足を目的としているため、「COMPOSE を用いた ANDROID アプリ開発の基礎」コースで心配になった時、エラーが起きて詰まった時や、分からないことがあった時、軽く復習したい時に見てください!
また、目次を見て自分に必要なところだけ見るのをお勧めします!

この記事を作成するにあたり使用しているAndroid StudioのバージョンはGiraffeです。バージョンによってはUIが違うことがあるのでご了承ください。
また、2024年5月7日現在の「COMPOSE を用いた ANDROID アプリ開発の基礎」コースを参考にしています。


学習内容

WorkManager

WorkManagerはユーザーがアプリを離れても実行する必要があるタスクを実行する必要がある場合に用います。
(アプリを離れても実行する必要があるタスクを実行する = 永続的である処理といいます。)
そのため、サーバーから定期的にデータを取得する、歩数計データを取得するなどの用途で使われています。
(身近な例として、恐らくですが、アプリを開いていないのにも関わらず歩数計アプリで一時間おきの歩数データが表示される裏には定期的にバックグラウンドで歩数計データを取得するように設定されているからだと思います。)
コルーチンとの違いは、コルーチンはアプリを閉じられると終了しますので永続的である処理には向きません。

参考

WorkManagerの特徴

WorkMangerの特徴の中でも、Codelabsで実際に体験したものは以下の5つです。

1.非同期の1回限りのタスクと定期的なタスクの両方をサポートCoroutineWorkerを使用することで非同期のタスクも行うことが出来ます。
また、1回だけのタスクの場合はOneTimeWorkRequest、定期的に行われるタスクの場合はPeriodicWorkRequestを使用することによって様々なタスクを実行できます。

2.タスクを実行する制約を指定できる
例えば、ネットワーク状態や容量に空きがあるか、充電ステータスなど

Codelabsより、充電ステータスの制約の例

3.処理の並列実行など、複雑な処理リクエストのチェーンを作成可能
WorkManagerの処理チェーンを使用することでWorkRequestを順次又は並列に実行できます。
※今回のCodelabsでは順次実行のみでした

今回のCodelabsで作成したアプリの処理チェーン

4.処理リクエストの出力を後続の処理リクエストの入力として使用可能
チェーンを作ることで、ひとつ前の出力を入力として受け取ることが出来ます。

5.一意処理
下のサイトに書かれている通り、一意処理とは「特定の名前が付けられた処理インスタンスが同時に 1 つだけ存在することを保証する」ものです。
そのため、今回のアプリは画像にぼかし処理をするというものでしたが、このぼかし処理はある時間において1つだけしか存在しません。
今回はぼかし処理中に別のぼかし処理を入れる場合は現在の処理を停止し、新しい処理を始めるように定義しています。

WorkMangerのクラス

1.Worker/CoroutineWorker
Workerクラスはバックグラウンドスレッドで同期 / 非同期処理をするクラスです。このクラスを拡張し、オーバーライドしたdo work()メソッドにバックグラウンドで実行する処理のコードを書きます。
要は処理の内容をここに書きます。

Worker

2.WorkRequest
ワーカーを一回だけ実行するかそれとも定期的に実行するかを定義します。また、特定の条件で実行する必要がある場合は制約も定義します。

WorkrRequest

3.WorkManager
workRequestをスケジュールして実行します。
下の画像に出てくる変数continuationの意味は「継続」。ここでは処理チェーンのことをさしている。

WorkManager

WorkManagerの使用法

①アプリに依存関係を追加する
次のサイトから最新の安定版を追加します。
https://developer.android.com/jetpack/androidx/releases/work?hl=ja)
※後述する注意点に書かれていますが、2024/5/10現在の安定版である version 2.9.0はエラーが起こることがあるため、その場合は2.8.1を使用してください。

//モジュールレベルのbuild.gradle.kts内
dependencies {

    ...
    implementation("androidx.work:work-runtime-ktx:2.8.1")
    ...
}

②Workerを作成する
同期コードを実行したいならWorkerクラスを、非同期コードを実行するならCoroutineWorkerクラスを拡張してWorkerを作成します。
バックグラウンド処理を行う際はdoWork()メソッドをオーバーライドします。このdoWork()から戻った際にワーカーは完了したとみなされ、破棄されます。
CoroutineWorkerではdoWork()内でwithContext()を使用することで作業を実行するコルーチンディスパッチャを指定できます。指定がない場合はDispatchers.Defaultです。

Workerの作成

③Dataオブジェクトを使用してWorkerにデータを入力、出力させる
Key-Valueペアの軽量なコンテナであるDataオブジェクトによって、Workerと WorkRequest との間でデータを受け渡しします。
WorkManagerで、Data.Builderを使用して入力データオブジェクトを作成し、WorkerのdoWork()内でinputDataを使用して入力データオブジェクトにアクセスします。その後、Worker内で出力データオブジェクトを作成する場合はworkDataOf() 関数を使用します。

WorkManager内で入力データオブジェクトを作成
Worker内で入力データオブジェクトにアクセス
出力データオブジェクトを作成、WorkRequestに返す

④WorkManagerでWorkRequestを作成してキューに追加する
1回だけの処理の場合はOneTimeWorkRequest、定期的に行われる処理の場合はPeriodicWorkRequestを使用してWorkRequestを作成します。
そして、WorkManagerによりWorkRequestをスケジュールし、enqueue() メソッドを呼び出すことで処理を開始します。
※下のコードではbeginUniqueWork()を用いることで処理チェーンは一意になっている。また、処理チェーンを使用しているため処理リクエストの出力を後続の処理リクエストの入力として使用している。

WorkManagerでWorkRequestを作成してキューに追加

⑤Workerをテストする
WorkManagerの実行にはContextが必要だったため、UIテストでテストします。
まず、プロジェクトに以下の3つの依存関係を追加します。

//モジュールレベルのbuild.gradle.kts内
dependencies {
    // Espresso
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
    // Junit
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    // Work testing
    androidTestImplementation("androidx.work:work-testing:2.8.1")
}

次にApplicationProviderを使用してコンテキストを取得した後、OneTimeWorkRequestBuilderの代わりにTestWorkerBuilder又はTestListenableWorkerBuilderを使用してWorkerを作成しテストします。

Workerのテスト

注意点

アクティビティ④「高度なWorkManagerとテスト」の⑧「Worker実装のテストを作成する」におけるエラー

アクティビティ④「高度なWorkManagerとテスト」の⑧「Worker実装のテストを作成する」において、依存関係を追加します。
この際、work-run-time-ktxの最新版を使用する必要があると書かれていますが、現在(2024/5/1)の最新版であるversion 2.9.0を使用すると以下のようなエラーが生じます。
そのため、version 2.8.1を使用してください。

エラー文
Cannot access 'androidx.work.CoroutineWorker' which is a supertype of 'com.example.bluromatic.workers.CleanupWorker'. Check your module classpath for missing or conflicting dependencies

エラーが発生する場所

さいごに

今回もCodelabsでの学習お疲れさまでした!
今回はWorkManagerを使用したバックグラウンドタスクに関する内容でした。いまいち用途についてピンと来ないかもしれませんが、重要な要素ですので必要になった時にぜひ復習してください!
次は、Composeを使用しない以前までのUIの記述法に関するお話です。まだ使用されているところが多くあるため、知っておいて損はない内容となっています。是非、Codelabsの学習を継続してください!


この記事が気に入ったらサポートをしてみませんか?