SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

一歩進んだAndroidアプリ開発ができる「Android Jetpack」入門

WorkManagerの発展的な使い方を解説 ──ワークチェイン、優先実行ワーカー、ワーカーの繰り返し実行

一歩進んだAndroidアプリ開発ができる「Android Jetpack」入門 第11回

  • X ポスト
  • このエントリーをはてなブックマークに追加

優先実行ワーカー

 ワークチェインの話はここまでとして、話題を優先実行ワーカーに変えます。

優先実行ワーカーとは

 優先実行ワーカーは、公式サイトでExpedited Workと記載されているワーカーのことです。第9回で紹介したように、WorkRequestに各種設定を行うことで、ワーカーの実行タイミングをある程度制御できます。

 しかし、ワーカー自体がそもそもバックグラウンドで動作することを前提としているため、当初は優先度の高いワーカーの実行向けの設定が存在していませんでした。その点を改善するために、WorkManagerのバージョン2.7より導入されたのが、このExpedited Work(優先実行ワーカー)です。

 優先実行ワーカーの利用ケースとして、画像共有アプリなど、ユーザーが何かファイルをアップロードし、アップロードしたファイルの内容をすぐに画面に反映させる必要がある場合などを挙げることができます。他にも、公式ドキュメントには、決済アプリや登録アプリなどが例として挙げられています。これらのアプリでは、処理そのものは非同期、バックグラウンドで行うのが最適ですが、その処理結果の反映は、同期処理並の速さを求められます。そのような場合に、優先実行ワーカーを利用します。

優先実行ワーカーの設定

 優先実行ワーカーを実行する場合、WorkRequestビルダーのsetExpedited()メソッドを使い、Java、Kotlinともにリスト7のコードとなります。

リスト7:優先実行ワーカーの実行コード
workRequestBuilder.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)

 このsetExpedited()メソッドは、引数としてOutOfQuotaPolicyの定数(より正確にはenum列挙子)を指定します。ここに登場したQuotaというのは、OSによって割り当てられる優先実行ワーカーのためのリソース(割り当て時間)のことを指します。ただし、これはワーカーを実行させるアプリがバックグラウンドに移行した場合の設定です。

 例えば、画面にボタンを配置し、そのボタンをタップすると優先実行ワーカーが実行されるとします。そして、ボタンをタップした後も、アプリの画面を表示させた状態、すなわち、アプリがフォアグラウンドのままの場合は、優先実行ワーカーの処理時間が制限されることはありません。

 一方アプリを終了したり、別のアプリを起動したりなど、アプリがバックグラウンドに回った場合は、Quotaという考えが有効になり、優先実行ワーカーは、このQuotaの範囲内で処理を終わらせる必要があります。そして、このQuotaの範囲内に処理が終了しなかった場合の挙動を指定するのが、setExpedited()メソッドの引数、すなわち、OutOfQuotaPolicyの列挙子です。

 このOutOfQuotaPolicyの列挙子は以下の2個あり、そのどちらかを選択します。

  • RUN_AS_NON_EXPEDITED_WORK_REQUEST
    優先実行ワーカーは、通常のワーカーとして扱われ、処理が継続されます。
  • DROP_WORK_REQUEST
    優先実行ワーカーの処理はキャンセルされます。

繰り返し実行のWorkRequest

 WorkManagerを紹介してきた本稿もこれで最後です。ここまでは、全てOneTimeWorkRequestに関するお話でした。最後にWorkManagerによるもうひとつのバックグラウンド処理であるPeriodicWorkRequestを紹介します。

PeriodicWorkRequestのWork States

 PeriodicWorkRequestは、ワーカーを繰り返し実行するWorkRequestです。このWorkRequestを利用した場合、ワーカーの状態はOneTimeWorkRequestとは違い、非常にシンプルになります。

 図6は、Androidの公式ドキュメントに掲載されている図です。

図6:PeriodicWorkRequestのWork States(出典:Androidの公式ドキュメント)
図6:PeriodicWorkRequestのWork States(出典:Androidの公式ドキュメント

 ENQUEUED、RUNNING、CANCELLEDの3種しかありません。PeriodicWorkRequestでは、ワーカーの処理が失敗しても成功しても、キューに戻され、設定された間隔で実行されます。もちろん、リトライでも同じです。そして、キャンセル処理が行われるまで、この繰り返しは続きます。

PeriodicWorkRequestの実行

 このように繰り返しワーカーを実行する場合のコードは、Javaならばリスト8、Kotlinならばリスト9となります。

リスト8:繰り返しワーカーの実行(Java版)[MainActivity.java]
PeriodicWorkRequest.Builder workRequestBuilder = new PeriodicWorkRequest.Builder(CountWorker.class, 20, TimeUnit.MINUTES);
リスト9:繰り返しワーカーの実行(Kotlin版)[MainActivity.kt]
val workRequestBuilder = PeriodicWorkRequestBuilder<CountWorker>(20, TimeUnit.MINUTES)

 WorkRequestのビルダーを生成する際、PeriodicWorkRequestのビルダーを生成するのがポイントです。Javaならば、PeriodicWorkRequest.Builderをnewします。一方、KotlinならばPeriodicWorkRequestBuilderインスタンスを生成します。

その際、Javaならば、第1引数に実行するワーカークラスを指定します(第2引数以降は後述します)。Kotlinならば、ジェネリクスとしてワーカークラスを型指定します。あとは、OneTimeWorkRequest同様に、PeriodicWorkRequestのビルダーからPeriodicWorkRequestを生成し、WorkManagerのキューに登録します。

繰り返し間隔を指定する引数

 PeriodicWorkRequestは、ワーカーを繰り返し実行するためのWorkRequestです。この繰り返し実行する間隔を指定するのが、ビルダーを生成する際の引数です。

 Javaの場合の第2引数とKotlinの場合の第1引数には数値を指定し、その数値が表す単位をJavaでは第3引数に、Kotlinでは第2引数に指定します。このパターンは、これまでも登場しているのでお分かりと思います。リスト8やリスト9では、数値は20、単位はTimeUnit.MINUTESとなっているので、20分間隔でワーカーが実行されることになります。

 なお、繰り返しの間隔の最小値は、PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS定数で表されるミリセカンド値であり、現在900000ミリセカンド(=15分)となっています。

 また、このPeriodicWorkRequestには、Flex Periodという考え方が導入されています。これは、実際にワーカーが実行されるタイミングに幅を持たせたものです。図7は、Androidの公式ドキュメントに掲載されている図です。

図7:Flex Periodの考え方(出典:Androidの公式ドキュメント)
図7:Flex Periodの考え方(出典:Androidの公式ドキュメント

 図7にある「interval」が繰り返し間隔であり、リスト8やリスト9では20分です。このうち、実際にワーカーが実行できるタイミングに幅を持たせたのが、図7中の「flex period can run work」の部分です。この範囲のどこかで、OSのタイミングがよいところで、ワーカーが実行されるようになり、この時間幅のことをフレックス間隔(Flex Interval)といいます。

 このような実行間隔を指定する場合は、リスト8やリスト9のビルダーの生成コードにさらに引数を2個増やし、Javaならばリスト10、Kotlinならばリスト11のようなコードになります。この場合は、フレックス間隔として6分を指定しているため、20分中の14分を過ぎれば、それ以降どこかでワーカーが実行されることになります。

リスト10:フレックス間隔を導入した例(Java版)[MainActivity.java]
PeriodicWorkRequest.Builder workRequestBuilder = new PeriodicWorkRequest.Builder(CountWorker.class, 20, TimeUnit.MINUTES, 6, TimeUnit.MINUTES);
リスト11:フレックス間隔を導入した例(Kotlin版)[MainActivity.kt]
val workRequestBuilder = PeriodicWorkRequestBuilder<CountWorker>(20, TimeUnit.MINUTES, 6, TimeUnit.MINUTES)

 なお、フレックス間隔を指定できる最小値は、PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS定数で表されるミリセカンド値であり、現在300000ミリセカンド(=5分)となっています。

まとめ

 Android Jetpackについて紹介していく本連載の第11回は、いかがでしたでしょうか。今回は3回にわたって紹介したWorkManagerの最後として、ワークチェイン、優先実行ワーカー、ワーカーの繰り返し実行を紹介しました。次回はPagingを紹介します。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
一歩進んだAndroidアプリ開発ができる「Android Jetpack」入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 齊藤 新三(サイトウ シンゾウ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。Web系製作会社のシステム部門、SI会社を経てフリーランスとして独立。屋号はSarva(サルヴァ)。HAL大阪の非常勤講師を兼務。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/20048 2024/08/30 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング