SHOEISHA iD

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

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

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

バックグラウンド処理を管理しよう! WorkManagerの基本の使い方を解説

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


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

WorkManagerの基本の使い方

 では、早速、実際にコードを交えながら、WorkManagerの使い方の基本を紹介していきます。

WorkManagerの使い方手順

 WorkManagerを利用する場合は、以下の手順となります。

  1. ワーカーの用意
  2. WorkRequestの用意
  3. WorkManagerへのWorkRequestの登録

 以下、順にコードを交えて紹介していきます。ただし、これらのコードを記述するプロジェクト、すなわち、WorkManagerを利用するプロジェクトでは、あらかじめその設定を行っておく必要があります。これは、build.gradle.kts(:app)ファイルのdependenciesブロックへの、リスト1の2行のコードの追記です。なお、work_versionのバージョン番号は、原稿執筆時点での番号です。最新バージョンに関しては、こちらのページを参照してください。

リスト1:build.gradle.kts(:app)へのWorkManagerを利用する設定
dependencies {
  val work_version = "2.9.0"
  implementation("androidx.work:work-runtime:$work_version")
  :
}

1. ワーカーの用意

 この手順は、ワーカークラスを用意することです。このワーカークラスでは、実際にバックグラウンドで行いたい処理を記述します。例えば、Javaではリスト2のようなクラスです。

リスト2:ワーカークラスの例であるCountUpWorker(Java版)
public class CountUpWorker extends Worker {  // (1)
  public CountUpWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {  // (2)
    super(context, workerParams);  // (3)
  }
  @NonNull
  @Override
  public Result doWork() {  // (4)
    :
    return Result.success();  // (5)
  }
}

 ワーカークラスを作成する場合、まず、(1)のように、Workerクラスを継承して作ります。このWorkerクラスを継承すると、必ず以下の2点を行わないとコンパイルエラーとなります。

  • コンストラクタの定義
  • doWork()の実装

 以下、順に説明します。

 まず、Workerクラスのコンストラクタには引数が設定されているため、Workerクラスを継承したクラスでは、(2)のようにコンストラクタを定義し、その中で(3)のようにsuper()を実行する必要があります。(2)のコンストラクタの引数定義は、(3)のsuper()に渡す2個の引数をそのまま定義します。これらの引数は、ワーカーを実行する際に内部で利用されるため、特別なコーディングは不要です。

 次に、doWork()の実装に関してです。Workerクラスは抽象クラスとなっており、このdoWork()が抽象メソッドとなっています。そのため、継承すると必ず(4)のdoWork()メソッドを実装する必要があります。そして、このメソッド内に、バックグラウンドで行いたい処理を記述し、最終的に(5)のResult.success()をリターンします。この意味については、次節で紹介します。

 このワーカークラスをKotlinで記述した例は、リスト3のようになります。リスト2のコードをそのままKotlinに置き換えただけとなるので、特に解説は不要でしょう。

リスト3:ワーカークラスの例であるCountUpWorker(Kotlin版)
class CountUpWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) {
  override fun doWork(): Result {
    :
    return Result.success();
  }
}

2. WorkRequestの用意

 バックグラウンド処理が記述されたワーカークラスが用意されたので、このワーカークラスを実際に起動してバックグラウンド処理を行っていきます。といっても、アクティビティやフラグメント、あるいは、ViewModelやリポジトリなどのUIスレッドオブジェクト内で、このワーカークラスをnewしてdoWork()メソッドを実行するわけではありません。代わりに行うのが、先の手順の2と3です。ここでは、そのうち手順の2のWorkRequestの用意を紹介します。基本コードは、Javaならばリスト4、Kotlinならばリスト5の1行だけです。

リスト4:WorkRequestを用意するコード(Java版)
WorkRequest workRequest = OneTimeWorkRequest.from(CountUpWorker.class);
リスト5:WorkRequestを用意するコード(Kotlin版)
val workRequest = OneTimeWorkRequest.from(CountUpWorker::class.java)

 このコードの通り、OneTimeWorkRequestクラスのstaticメソッドであるfrom()を実行するだけで、WorkRequestが用意できます。その際、引数として、実行したいワーカークラスを渡します。

 ただし、ここで紹介した方法は、ごく基本中の基本であり、実際には、このWorkRequestを用意する手順にさまざまなバリエーションがあります。それらに関して、次節以降紹介していきます。

3. WorkManagerへのWorkRequestの登録

 最後の手順が、WorkManagerへのWorkRequestの登録であり、Javaならばリスト6、Kotlinならばリスト7のコードとなります。

リスト6:WorkManagerへのWorkRequestの登録コード(Java版)
WorkManager workManager = WorkManager.getInstance(MainActivity.this);
workManager.enqueue(workRequest);
リスト7:WorkManagerへのWorkRequestの登録コード(Kotlin版)
val workManager = WorkManager.getInstance(this@MainActivity)
workManager.enqueue(workRequest)

 これらのコードは、最終的にWorkManagerオブジェクトのenqueue()メソッドを実行するコードです。その際、手順2で用意したWorkRequestオブジェクトを渡します。

 そのために、リスト6もリスト7も、1行目でWorkManagerインスタンスを取得しています。これは、WorkManagerのstaticメソッドのgetInstance()を実行します。その際、コンテキストを渡します。

 もちろん、リスト6もリスト7も可読性を重視し、2行でコードを記述していますが、以下のように1行でコードを記述してもかまいません。

WorkManager.getInstance(MainActivity.this).workManager.enqueue(workRequest);

 このコードが実行された段階で、ワーカーオブジェクトがWorkManagerに登録され、その後は、WorkManagerがOSなどのさまざまな状況を確認しながら、適切なタイミングで登録されたワーカーオブジェクトのdoWork()メソッドが実行されます。

 なお、これらのワーカーの実行は、すべてバックグラウンドで行われるため、原則、その実行状況は確認できませんし、確認する必要はありません。ただし、開発段階では、デバッグの関係上、確認したい場合もあります。その場合は、こちらにあるように、Android Studioのバックグラウンドタスクインスペクタから確認できます。

Work StatesとdoWork()の戻り値

 WorkManagerの基本を紹介したところで、ワーカーのコードについて解説していないところ、すなわち、リスト2の(5)のdoWork()も戻り値の意味に関して説明していきます。

ワーカーの状態を表すWork States

 doWork()の戻り値の意味を理解するには、Work Statesを理解する必要があります。これは、ワーカーの処理の状態を表します。この状態を解説するために、Androidの公式ドキュメントには、図1が掲載されています。

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

 リスト6やリスト7のコードでWorkManagerのenqueue()メソッドが実行された時点で、WorkRequestに登録されているワーカーはENQUEUED状態になります。そして、WorkRequestに設定された内容に応じて、適切なタイミングでワーカーが実行され、RUNNINGの状態になります。なお、リスト4やリスト5のfrom()メソッドにより生成されたWorkRequestは、全く設定が行われていない、デフォルトのWorkRequestとなります。

 RUNNINGの状態のワーカーは、終了状態にならない限りは、ENQUEUED状態に戻されます。これをリトライ(RETRY)といいます。では、終了状態とは何かというと、図1の右側3個、すなわち、処理が成功したSUCCEEDED、処理が失敗したFAILED、処理をキャンセルしたCANCELLEDです。なお、キャンセルに関しては、図1の矢印の通り、ENQUEUED状態から直接CANCELLEDに移行することが可能であり、いずれにせよ、キャンセル処理が行われた場合です。

doWork()の戻り値

 一方、SUCCEEDEDとFAILED、さらに、RETRYに関しては、doWork()の戻り値として指定できます。この仕組みを利用して、doWork()メソッド内は、リスト8のようなコードパターンとすることができます。

リスト8:doWork()メソッド内のコードパターン
public Result doWork() {
  :
  Result returnVal = Result.success();  // (1)
  if(処理を再実行したい場合) {
    returnVal = Result.retry();  //  (2)
  }
  else if(処理を失敗としたい場合) {
    returnVal = Result.failure();  // (3)
  }
  return returnVal;
}

 ポイントは、リスト2の(5)で紹介したResult.success()だけではなく、このワーカーを再実行したい場合は、リスト8の(2)のように、Result.retry()を戻り値とできることです。同様に、このワーカーの実行失敗としたい場合は、(3)のResult.failure()を戻り値とできます。もちろん、必ずResultオブジェクトを戻り値としなければならないため、リスト8のコードパターンでは、(1)のように、デフォルトでResult.success()を戻り値とするようにしています。なお、ソースコードの掲載は割愛しますが、Kotlinでも同様のコードパターンとします。

次のページ
WorkRequestへの設定

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

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

もっと読む

この記事の著者

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

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/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/19461 2024/05/21 14:32

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング